将浮点转换为定点

发布于 2024-07-07 13:29:20 字数 440 浏览 6 评论 0原文

在 C++ 中,将任何浮点值 (float) 转换为定点<的通用方法是什么/strong>(实时,16:16 或 24:8)?

编辑:为了澄清,定点值有两个部分:整数部分和小数部分。 整数部分可以由有符号或无符号整数数据类型表示。 小数部分由无符号数据整数数据类型表示。

为了清楚起见,让我们用金钱做一个类比。 小数部分可以代表美分——一美元的小数部分。 “cents”数据类型的范围为 0 到 99。如果要使用 8 位无符号整数进行定点数学,则小数部分将被分成 256 个可整除的部分。

我希望事情能够澄清。

In C++, what's the generic way to convert any floating point value (float) to fixed point (int, 16:16 or 24:8)?

EDIT: For clarification, fixed-point values have two parts to them: an integer part and a fractional part. The integer part can be represented by a signed or unsigned integer data type. The fractional part is represented by an unsigned data integer data type.

Let's make an analogy with money for the sake of clarity. The fractional part may represent cents -- a fractional part of a dollar. The range of the 'cents' data type would be 0 to 99. If a 8-bit unsigned integer were to be used for fixed-point math, then the fractional part would be split into 256 evenly divisible parts.

I hope that clears things up.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

_畞蕅 2024-07-14 13:29:21

这对于从浮点转换为整数来说很好,但是OP还想要定点

现在,我不知道如何在 C++ 中做到这一点(C++ 不是我可以轻易思考的东西)。 也许可以尝试缩放整数方法,即使用 32 或 64 位整数并以编程方式将最后 6 位数字分配给小数点右侧的数字。

This is fine for converting from floating point to integer, but the O.P. also wanted fixed point.

Now how you'd do that in C++, I don't know (C++ not being something I can think in readily). Perhaps try a scaled-integer approach, i.e. use a 32 or 64 bit integer and programmatically allocate the last, say, 6 digits to what's on the right hand side of the decimal point.

无声情话 2024-07-14 13:29:21

C++ 中没有对定点数的内置支持。 最好的选择是编写一个包装器“FixedInt”类,它接受双精度数并转换它们。

至于转换的通用方法... int 部分很简单,只需获取值的整数部分并将其存储在高位中...小数部分将类似于:

for (int i = 1; i <= precision; i++)
{
   if (decimal_part > 1.f/(float)(i + 1)
   {
      decimal_part -= 1.f/(float)(i + 1);
      fixint_value |= (1 << precision - i);
   }
}

尽管这很可能仍然包含错误

There isn't any built in support in C++ for fixed point numbers. Your best bet would be to write a wrapper 'FixedInt' class that takes doubles and converts them.

As for a generic method to convert... the int part is easy enough, just grab the integer part of the value and store it in the upper bits... decimal part would be something along the lines of:

for (int i = 1; i <= precision; i++)
{
   if (decimal_part > 1.f/(float)(i + 1)
   {
      decimal_part -= 1.f/(float)(i + 1);
      fixint_value |= (1 << precision - i);
   }
}

although this is likely to contain bugs still

冷夜 2024-07-14 13:29:20

给你:

// A signed fixed-point 16:16 class
class FixedPoint_16_16
{
    short          intPart;
    unsigned short fracPart;

public:
    FixedPoint_16_16(double d)
    {
        *this = d; // calls operator=
    }

    FixedPoint_16_16& operator=(double d)
    {
        intPart = static_cast<short>(d);
        fracPart = static_cast<unsigned short>
                    (numeric_limits<unsigned short> + 1.0)*d);
        return *this;
    }

    // Other operators can be defined here
};

编辑:这是一个更通用的类,基于处理定点数的另一种常见方法(KPexEA 指出了这一点):

template <class BaseType, size_t FracDigits>
class fixed_point
{
    const static BaseType factor = 1 << FracDigits;

    BaseType data;

public:
    fixed_point(double d)
    {
        *this = d; // calls operator=
    }

    fixed_point& operator=(double d)
    {
        data = static_cast<BaseType>(d*factor);
        return *this;
    }

    BaseType raw_data() const
    {
        return data;
    }

    // Other operators can be defined here
};


fixed_point<int, 8> fp1;           // Will be signed 24:8 (if int is 32-bits)
fixed_point<unsigned int, 16> fp1; // Will be unsigned 16:16 (if int is 32-bits)

Here you go:

// A signed fixed-point 16:16 class
class FixedPoint_16_16
{
    short          intPart;
    unsigned short fracPart;

public:
    FixedPoint_16_16(double d)
    {
        *this = d; // calls operator=
    }

    FixedPoint_16_16& operator=(double d)
    {
        intPart = static_cast<short>(d);
        fracPart = static_cast<unsigned short>
                    (numeric_limits<unsigned short> + 1.0)*d);
        return *this;
    }

    // Other operators can be defined here
};

EDIT: Here's a more general class based on anothercommon way to deal with fixed-point numbers (and which KPexEA pointed out):

template <class BaseType, size_t FracDigits>
class fixed_point
{
    const static BaseType factor = 1 << FracDigits;

    BaseType data;

public:
    fixed_point(double d)
    {
        *this = d; // calls operator=
    }

    fixed_point& operator=(double d)
    {
        data = static_cast<BaseType>(d*factor);
        return *this;
    }

    BaseType raw_data() const
    {
        return data;
    }

    // Other operators can be defined here
};


fixed_point<int, 8> fp1;           // Will be signed 24:8 (if int is 32-bits)
fixed_point<unsigned int, 16> fp1; // Will be unsigned 16:16 (if int is 32-bits)
倾城°AllureLove 2024-07-14 13:29:20

从浮点到整数的转换会丢弃小数部分,因此如果您想将该分数保留为固定点,那么您只需在转换之前乘以浮点即可。 请注意,下面的代码不会检查溢出。

如果你想要 16:16

double f = 1.2345;
int n;

n=(int)(f*65536);

如果你想要 24:8

double f = 1.2345;
int n;

n=(int)(f*256);

A cast from float to integer will throw away the fractional portion so if you want to keep that fraction around as fixed point then you just multiply the float before casting it. The below code will not check for overflow mind you.

If you want 16:16

double f = 1.2345;
int n;

n=(int)(f*65536);

if you want 24:8

double f = 1.2345;
int n;

n=(int)(f*256);
流年已逝 2024-07-14 13:29:20

**** 编辑** :我的第一条评论适用于凯文的编辑之前,但我会将其留在这里供后代使用。 有时答案变化得很快!

Kevin 方法的问题在于,使用定点,您通常会打包成有保证的字大小(通常为 32 位)。 分别声明这两个部分让您可以随意调整编译器的结构打包。 是的,您可以强制它,但它不适用于 16:16 表示以外的任何内容。

KPexEA 通过将所有内容打包到 int 中来更接近目标 - 尽管我会使用“signed long”来尝试在 32 位上明确。 然后您可以使用他的方法来生成定点值,并且位切片会再次提取组成部分。 他的建议也涵盖了 24:8 的情况。

(以及其他建议使用 static_cast 的人......你在想什么?;))

**** Edit** : My first comment applies to before Kevin's edit,but I'll leave it here for posterity. Answers change so quickly here sometimes!

The problem with Kevin's approach is that with Fixed Point you are normally packing into a guaranteed word size (typically 32bits). Declaring the two parts separately leaves you to the whim of your compiler's structure packing. Yes you could force it, but it does not work for anything other than 16:16 representation.

KPexEA is closer to the mark by packing everything into int - although I would use "signed long" to try and be explicit on 32bits. Then you can use his approach for generating the fixed point value, and bit slicing do extract the component parts again. His suggestion also covers the 24:8 case.

( And everyone else who suggested just static_cast.....what were you thinking? ;) )

束缚m 2024-07-14 13:29:20

我给了写出最佳答案的人的答案,但我确实使用了一个相关的问题代码,该代码指向此处

它使用模板,并且很容易摆脱对 boost 库的依赖。

I gave the answer to the guy that wrote the best answer, but I really used a related questions code that points here.

It used templates and was easy to ditch dependencies on the boost lib.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文