显然相同的数学表达式具有不同的输出 [英] Apparently identical math expressions with different output

查看:69
本文介绍了显然相同的数学表达式具有不同的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码在x86 32位计算机上将为变量'e'和'f'输出不同的结果,但在x86 64位计算机上将输出相同的结果.为什么?从理论上讲,正在评估相同的表达式,但从技术上讲,不是.

The following code will output different results for variables 'e' and 'f' on a x86 32 bit machine but the same results on a x86 64 bit machine. Why? Theoretically the same expression is being evaluated, but technically it is not.

#include <cstdio>
main()
{
  double a,b,c,d,e,f;
  a=-8988465674311578540726.0;
  b=+8988465674311578540726.0;
  c=1925283223.0;
  d=4294967296.0;
  e=(c/d)*(b-a)+a;
  printf("%.80f\n",e);
  f=c/d;
  f*=(b-a);
  f+=a;
  printf("%.80f\n",f);
}

注意...使用'gcc -m32'可以生成32位x86代码,感谢@Peter Cordes https://stackoverflow.com/users/224132/peter-cordes

Note ... 32 bit x86 code can be generated with 'gcc -m32' ,thanks @Peter Cordes https://stackoverflow.com/users/224132/peter-cordes

另请参见

增强了: :random :: uniform_real_distribution应该在处理器之间相同吗?

-用户Madivad的更新

--- update for user Madivad

64 bit output 
-930037765265417043968.00000...
-930037765265417043968.00000...

32 bit output
-930037765265416519680.00000...
-930037765265417043968.00000...

此python代码可以给出数学上正确的"输出

The "mathematically correct" output can be given by this python code

from fractions import Fraction
a=-8988465674311578540726
b=8988465674311578540726
c=1925283223
d=4294967296
print "%.80f" % float(Fraction(c,d)*(b-a)+a)

-930037765265416519680.000...

推荐答案

FLT_EVAL_METHOD.

C允许根据FLT_EVAL_METHOD在更高/更广泛的类型上进行中间FP计算.因此,当使用更广泛的类型并且代码流不同时,尽管数学上相等,但结果可能会略有不同.

C allows intermediate FP calculations to occur at higher/wider types depending on FLT_EVAL_METHOD. So when wider types are used and code flow differs, though mathematically equal, slightly different results may occur.

除了赋值和强制类型转换(这会删除所有额外的范围和精度)之外,具有浮动操作数的运算符产生的值以及需要进行常规算术转换的值和具有浮动常数的值都将被评估为其范围和精度可能更大的格式超出类型要求.评估格式的使用具有特点 通过实现定义的FLT_EVAL_METHOD值:

Except for assignment and cast (which remove all extra range and precision), the values yielded by operators with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type. The use of evaluation formats is characterized by the implementation-defined value of FLT_EVAL_METHOD:

-1.不确定的;
0.仅根据类型的范围和精度评估所有运算和常量;
1.评估float和double类型的运算和常数,以double类型的范围和精度,评估long double运算和常数,以long double类型的范围和精度;
2.评估所有运算和常量,使其达到范围和精度. 长双字型.
C11dr§5.2.4.2.29

-1. indeterminable;
0. evaluate all operations and constants just to the range and precision of the type;
1. evaluate operations and constants of type float and double to the range and precision of the double type, evaluate long double operations and constants to the range and precision of the long double type;
2. evaluate all operations and constants to the range and precision of the long double type.
C11dr §5.2.4.2.2 9

@Pascal Cuoq 有一个有用的评论关于FLT_EVAL_METHOD的准确性.在任何情况下,沿各种代码路径进行优化的FP代码都可能呈现不同的结果.当FLT_EVAL_METHOD != 0或编译器不严格遵守时,可能会发生这种情况.

@Pascal Cuoq has a useful comment on the veracity on FLT_EVAL_METHOD. In any case, FP code, optimized different along various code paths, may present different results. This may occur when FLT_EVAL_METHOD != 0 or compiler is not strictly conforming.

关于帖子的详细信息:在*然后在+的2个操作中完成的X*Y + Z运算可以与fma()进行对比,其中计算(x×y)+ z,四舍五入为一个三进制数"操作:他们将值(好像)计算为无限精度,并根据当前的舍入模式舍入一次为结果格式." C11§7.12.13.12.结果差异的另一个候选者可能是由于在行e=(c/d)*(b-a)+a;

Concerning a detail of the post: the operation X*Y + Z done in 2 operations of * and then + could be contrasted with fma() which "compute (x × y) + z, rounded as one ternary operation: they compute the value (as if) to infinite precision and round once to the result format, according to the current rounding mode." C11 §7.12.13.1 2. Another candidate for the difference in results could be due to the application "fma" to the line e=(c/d)*(b-a)+a;

这篇关于显然相同的数学表达式具有不同的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆