Java vs C浮点数:“x * x”不同于“pow(x,2)”?

为什么这是真的?当与C和Java Math.pow方法相比,当乘以两个浮点数时,Java似乎产生一个小的差异的结果。

Java的:

float a = 0.88276923;

double b = a * a;   // b becomes 0.779281497001648  <---- what???
b = Math.pow(a,2);  // b becomes 0.7792815081874238

C:

float a = 0.88276923;

double b = a * a;   // b becomes 0.7792815081874238
pow(a,2);           // b becomes 0.7792815081874238

更新:Per Ed S.的评论,我也发现C行为根据编译器而改变。使用gcc似乎符合Java行为。使用visual studio(取决于你的目标平台),它可以产生上面看到的结果或Java中看到的结果。啊。

随着pst和trutheality已经明智地指出,C在乘法之前将浮动推动到双倍。实际上,当它们被推到堆栈上时,它们被提升到80位的扩展精度值。这是汇编器输出(VS2005 x86 C89)

    double b = a * a;
00411397  fld         dword ptr [a] 
0041139A  fmul        dword ptr [a] 
0041139D  fstp        qword ptr [b] 

FLD指令

The FLD instruction loads a 32 bit, 64 bit, or 80 bit floating point value onto the stack. This instruction converts 32 and 64 bit operands to an 80 bit extended precision value before pushing the value onto the floating point stack.

有趣的是,如果我建立目标x64,则使用movss指令,并获得0.779281497001648的值,即您在Java示例中看到的值。试一试。

转载注明原文:Java vs C浮点数:“x * x”不同于“pow(x,2)”? - 代码日志