清除单个精度浮点数的位
C++: Clear bits of a single precision float
我目前正在将最初用于OpenCL的程序转换为c++,并且我在其中的一个特定部分遇到了一点麻烦。
上述程序中常用的表达式之一涉及将32位浮点数转换为整数(即不是实际将其舍入为int,而是将相同的数据解释为int -想想reinterpret_cast),对其执行一些位旋转魔术,然后将其转换回浮点数(再次不是实际转换,而是重新解释相同的数据)。虽然这在OpenCL中工作得很好,但在c++和gcc中,这违反了严格的别名规则,如果启用了优化,则会破坏程序,并且根据体系结构,可能涉及昂贵的load-hit-store,因为浮点寄存器和整数寄存器是分开的。
我已经能够有效地避免大多数这些表达式,但有一个我不确定是否可以更快地完成。基本上,这样做的目的是清除浮点数右侧的一些位;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(不含)之间的数字。
Thanks in advance
使用联合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++标准,写是非法的,如果对union的一个成员进行写操作,然后从另一个成员中读取,而不首先对该成员进行写操作,则的结果是未定义的。
然而,联合的这种用法是如此广泛和古老,以至于我所知道的编译器编写者都没有遵守这个标准。在实践中,该行为定义得非常好,并且正是您所期望的。也就是说,如果移植到一些非常奇怪的架构机器上,使用非常严格的编译器,这个hack可能无法工作。
重新解释为int
违反了混叠规则。将其重新解释为unsigned char[4]
则不然。是否需要支持NumberOfBits
值>=8 ?如果没有,你可以在ptr[3]
不能使用floor()而不是转换为int类型吗?
- 使用浮点数和双精度数的非常小数字的数学
- 为什么 std::cout 打印浮点数、双精度和长双精度到相同的小数精度?
- 位设置为浮点数或双精度值 c++
- 为什么浮点数的矢量化比双精度更有效?
- 在C++中序列化浮点数/双精度,编译为 WebAssembly
- 为什么编译器接受具有长双精度文本的浮点数的初始化?
- C++ 警告:在一个声明中将截断从双精度初始化为浮点数,但在另一个声明中则不初始化
- 在 OpenCL 内核中实现半精度浮点数据类型
- 如何随机化双精度/浮点数据类型? C++
- 提升多精度浮点数128:标准::exp错误:'no matching function for call'
- 如何提高计算浮点数的精度?
- atof() 返回浮点数而不是双精度
- 十六进制到浮点数 IEEE 754 双精度 c++
- C++浮点数与双胞胎设置精度奇数(新手)
- C++采用浮点数或双精度的模板函数
- 在 c++ 中使用浮点数、双精度打印十进制
- 为什么自动推断这个变量为双精度而不是浮点数?
- 我们如何清楚地知道 C/C++ 中的双精度或浮点数的精度?
- 为什么这种类型是双精度而不是浮点数
- GNU C++ 浮点数精度