是* b< a为0< = b< 1在IEEE浮点数中带正a?

时间:2015-02-12 02:46:44

标签: ieee-754

我用C ++编写,使用符合圆形到最近模式的IEEE算法。如果a是正短整数(16位)并且b是浮点数(32位),则其中0 <= b <1。 1,a * b&lt;总是评价为真?

1 个答案:

答案 0 :(得分:2)

也许。这取决于编译器如何决定评估浮点表达式(请阅读C99发明的FLT_EVAL_METHOD,但现在是C ++标准的一部分,如果你想要血腥细节的话。)

只要a可以大于4,当a*b为“大float时,表示为a的产品b会向b = 1-ε/2舍入足够的“,例如a*b(其中ε是1.0和下一个可表示的数字之间的差异,2 -23 。)但是如果编译器执行在中间评估中进行舍入,在比较之前,产品可以保持一些(更好的)内部精度,其中a仍然不同于(float)a*b < a,并且对内部精度的比较将是总是断言。这种情况并不罕见:由于x87协处理器的设计,将所有结果保持为64位长双倍是典型的32位x86架构,例如; 53位双精度值也会使所有值保持分离,因为24 + 16 <53。

假设编译器中没有错误,浮动的显式强制转换应该强制进行舍入,因此float 应该有时评估为false。在这里要特别谨慎,因为这个区域known显示编译器错误,特别是因为浮点被声明为“专家保留”,程序员通常建议依赖这些细节。您应特别注意激活编译器的优化选项(如/fp:fast),这些选项很可能跳过改善绩效的四舍五入行动。

执行测试的一种更安全(但仍然不是完全安全)的方法是将乘法结果显式存储到float c = a * b; if (c < a) call_Houston(); 变量中,例如

volatile float c = a * b;
  if (c < a) call_Houston();

再次,C ++标准需要显式舍入(这是非常合乎逻辑的,因为表达式的表示必须存储到32位浮点变量中。)但是这里再次提到了一些聪明的编译器,特别是在优化模式下,可能会猜测表达式在之后重复使用,并且可以采用短路径并重用寄存器内评估(具有更高的精度),并破坏您的努力(和让休斯顿不知道。)GCC编译器曾经建议在这种情况下向编译器提供类似

的代码
{{1}}

然后转到specific options like -ffloat-store。这并不能防止失去理智点。顺便说一句,最近版本的GCC在这方面更加明智(因为bug323是固定的。)