在线搜索,我发现以下例程用于计算IEEE格式的浮点符号。这也很容易扩展到双倍。
// returns 1.0f for positive floats, -1.0f for negative floats, 0.0f for zero
inline float fast_sign(float f) {
if (((int&)f & 0x7FFFFFFF)==0) return 0.f; // test exponent & mantissa bits: is input zero?
else {
float r = 1.0f;
(int&)r |= ((int&)f & 0x80000000); // mask sign bit in f, set it in r if necessary
return r;
}
}
(Source:``快速签署32位花车'',Peter Schoffhauzer)
但是,由于二进制位操作,我厌倦了使用这个例程。我需要我的代码在具有不同字节顺序的机器上工作,但我不确定IEEE标准中有多少指定,因为我找不到今年发布的最新版本。有人能告诉我这是否有效,无论机器的字节顺序如何?谢谢, 帕特里克
答案 0 :(得分:10)
您如何看待fabs()
和fabsf()
在您的系统上实施,或者与常数0进行比较?如果它不是按位运算,那很可能是因为编译器编写者认为不会更快。
此代码的可移植性问题是:
r
在以下行中修改之前已初始化为1.0。它可以重新排序操作。这不是空闲的推测,并且与(1)和(2)不同,它是未定义的,而不是实现定义的,因此您不一定只需查找编译器。通过足够的优化,我看到GCC跳过了浮点变量的初始化,这些浮点变量只能通过类型惩罚指针来引用。我会先做明显的事情并检查发出的代码。只有这看起来狡猾,才值得考虑做其他事情。我没有任何特别的理由认为我知道浮点数的位数表示比我的编译器更多; - )
inline float fast_sign(float f) {
if (f > 0) return 1;
return (f == 0) ? 0 : -1;
// or some permutation of the order of the 3 cases
}
[编辑:实际上,即使用-O3,海湾合作委员会也确实做了一顿饭。发出的代码不一定很慢,但它确实使用了浮点运算,因此不清楚它是否很快。因此,下一步是进行基准测试,测试替代方案是否可以更快地在您可以使用的任何编译器上进行测试,如果是这样,那么移植代码的人可以通过#define
或其他方式启用它们,根据他们自己的基准测试结果。]
答案 1 :(得分:3)
不要忘记将浮点值从FPU寄存器移动到整数寄存器需要写入RAM然后读取。
使用浮点代码,您可以更好地查看更大的图片:
Some floating point code
Get sign of floating point value
Some more floating point code
在上面的场景中,使用FPU确定符号会更快,因为没有写/读开销 1 。英特尔FPU可以:
FLDZ
FCOMP
设置> 0
,< 0
和== 0
的条件代码标记,可以与FCMOVcc
一起使用。
将上述内容写入编写良好的FPU代码将胜过任何整数位操作,并且不会丢失精度 2 。
注意: