[英]C++: Clear bits of a single precision float
我目前正在将原本打算用于OpenCL的程序转换为C ++,但其中的某个特定部分有些麻烦。
所述程序中常用的一种表达方式是采用32位浮点数,将其转换为整数(即,实际上不将其舍入为int,而是将相同的数据解释为int-请考虑reinterpret_cast),执行一些魔术操作。然后将其转换回浮点数(再次,不是实际转换,而是对相同数据的重新解释)。 尽管这在OpenCL中运行良好,但使用C ++和gcc却违反了严格的别名规则,如果启用了优化,则会破坏程序,并且由于体系结构的不同,由于浮点数和整数寄存器是分开的,因此可能涉及昂贵的加载命中存储。
我已经能够有效地避免大多数这些表达式,但是我不确定其中是否可以更快地完成。 基本上,目的是清除浮点数右边的一些位; OpenCL代码与此类似:
float ClearFloatBits(float Value, int NumberOfBits) {
return __int_as_float((__float_as_int(Value) >> NumberOfBits) << NumberOfBits);
}
由于这实际上是从指定的(二进制)数字取整,因此我的C ++版本现在看起来像这样:
float ClearFloatBits(float Value, int NumberOfBits) {
float Factor = pow(2.0f, 23 - NumberOfBits);
return ((int)(Value*Factor))/Factor;
}
当然, pow
和除法用LUT查找和相应的乘法代替,此处出于更好的可读性而省略。
有一个更好的方法吗? 特别令我烦恼的是要舍入的(int)转换,我认为这是最昂贵的部分。 如果有帮助,可以保证传递给函数的浮点数是介于1.0(含)和2.0(不含)之间的数字。
提前致谢
请改用Union Hack:
float ClearFloatBits(float Value, int NumberOfBits) {
union { unsigned int int_val; float flt_val; } union_hack;
union_hack.flt_val = Value;
(union_hack.int_val >>= NumberOfBits) <<= NumberOfBits;
return union_hack.flt_val;
}
严格来说,这是未定义的行为。 根据C和C ++标准,
将写入
结果写入联盟的一个成员然后从另一个成员读取而不先写入另一个成员是未定义的,
这是非法的
。
但是,这种联合的用法是如此广泛和古老,以至于我所认识的编译器作者都没有遵守该标准。 在实践中,行为定义得很清楚,正是您所期望的。 就是说,如果将该hack移植到使用非常严格符合要求的编译器的某些非常奇怪的体系结构计算机上,则可能无法正常工作。
重新解释为int
违反别名规则。 重新解释为unsigned char[4]
不会。 您是否需要支持NumberOfBits
值> = 8? 如果没有,您可以在ptr[3]
上进行ptr[3]
您不能使用floor()而不是转换为int吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.