在 C++ 中,将任何浮点值 (float) 转换为定点(int、16:16 或 24:8) 的通用方法是什么?
编辑:为澄清起见,定点值有两个部分:整数部分和小数部分。整数部分可以用有符号或无符号整数数据类型表示。小数部分由无符号数据整数数据类型表示。
为了清楚起见,让我们用金钱做一个类比。小数部分可能代表美分——一美元的小数部分。'cents' 数据类型的范围是 0 到 99。如果将 8 位无符号整数用于定点数学,那么小数部分将被分成 256 个可整除的部分。
我希望这能解决问题。
在 C++ 中,将任何浮点值 (float) 转换为定点(int、16:16 或 24:8) 的通用方法是什么?
编辑:为澄清起见,定点值有两个部分:整数部分和小数部分。整数部分可以用有符号或无符号整数数据类型表示。小数部分由无符号数据整数数据类型表示。
为了清楚起见,让我们用金钱做一个类比。小数部分可能代表美分——一美元的小数部分。'cents' 数据类型的范围是 0 到 99。如果将 8 位无符号整数用于定点数学,那么小数部分将被分成 256 个可整除的部分。
我希望这能解决问题。
干得好:
// 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)
从浮点数到整数的转换将丢弃小数部分,因此如果您想将该分数保持为固定点,那么您只需在转换之前乘以浮点数。下面的代码不会检查溢出提醒你。
如果你想要 16:16
double f = 1.2345;
int n;
n=(int)(f*65536);
如果你想要 24:8
double f = 1.2345;
int n;
n=(int)(f*256);
**** 编辑** :我的第一条评论适用于凯文的编辑之前,但我会把它留在这里以供后代使用。有时这里的答案变化如此之快!
Kevin 方法的问题在于,使用 Fixed Point,您通常会打包成有保证的字长(通常为 32 位)。分别声明这两个部分会让您随心所欲地使用编译器的结构包装。是的,你可以强制它,但它不适用于 16:16 表示以外的任何东西。
KPexEA 通过将所有内容打包到 int 中更接近标记 - 尽管我会使用“signed long”来尝试在 32 位上显式。然后你可以使用他的方法来生成定点值,并且位切片会再次提取组成部分。他的建议也涵盖了 24:8 的情况。
(以及其他只建议 static_cast 的人......你在想什么?;))
我把答案给了写出最佳答案的人,但我确实使用了指向此处的相关问题代码。
它使用模板并且很容易放弃对 boost 库的依赖。
这对于从浮点数转换为整数很好,但 OP 也需要定点数。
现在你如何在 C++ 中做到这一点,我不知道(C++ 不是我能轻易想到的东西)。或许可以尝试使用缩放整数方法,即使用 32 位或 64 位整数并以编程方式将最后一位(例如 6 位)分配给小数点右侧的内容。
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);
}
}
尽管这可能仍然包含错误