快速登录C++ float ...这段代码中是否有任何平台依赖?

Pat*_*ski 4 c++ floating-point endianness ieee-754

在线搜索,我发现以下例程用于计算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;
    }
}
Run Code Online (Sandbox Code Playgroud)

(来源:``32位漂浮物的快速标志'',Peter Schoffhauzer)

但是,由于二进制位操作,我厌倦了使用这个例程.我需要我的代码在具有不同字节顺序的机器上工作,但我不确定IEEE标准中有多少指定,因为我找不到今年发布的最新版本.有人能告诉我这是否有效,无论机器的字节顺序如何?

谢谢,帕特里克

Ste*_*sop 10

您如何看待fabs()fabsf()在您的系统上实施,或者与常数0进行比较?如果它不是按位操作,那很可能是因为编译器编写者不认为会更快.

此代码的可移植性问题是:

  1. float和int可能没有相同的字节序或甚至相同的大小.因此,面具可能是错误的.
  2. float可能不是IEEE表示
  3. 您打破严格的别名规则.允许编译器假定指向float的指针/引用和指向int的指针/引用不能指向相同的内存位置.因此,例如,标准不保证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
}
Run Code Online (Sandbox Code Playgroud)

[编辑:实际上,即使使用-O3,海湾合作委员会也确实做了一顿饭.发出的代码不一定很慢,但它确实使用了浮点运算,因此不清楚它是否很快.所以下一步是进行基准测试,测试你可以选择的任何编译器上的替代方案是否更快,如果是这样的话#define,根据他们自己的基准测试的结果,使人们移植你的代码可以使用或者其他任何东西. ]