为什么JavaScript的Math.pow()似乎返回一个四舍五入的值相比,在C中相同?

我的理解是,C的double和Javascript的数字都是IEEE 754 64位浮点数。 我试图将一些代码从C移植到Nodejs,并且我正在运行在JavaScript的Math.pow()似乎是舍入错误。

这是我的C程序:

 #include "stdio.h" #include "math.h" int main(int argc, char *argv[]) { double shared = 729; double exponent = 15; double prime = 1500450271; double power = pow(shared, exponent); double mod = fmod(power, prime); int intResult = (int) mod; printf("shared: %lf, exponent: %lf, prime: %lf, pow: %lf, mod: %lf, result: %i\n", shared, exponent, prime, power, mod, intResult); } 

其输出是:

 shared: 729.000000, exponent: 15.000000, prime: 1500450271.000000, pow: 8727963568087711970669458465954849888403456.000000, mod: 1488486878.000000, result: 1488486878 

有趣的是,当我尝试在JavaScript中执行此计算(在节点,Chrome,Firefox中testing)

我得到以下结果:

 > Math.pow( 729, 15) 8.727963568087713e+42 > Math.pow( 729, 15 ) % 1500450271; 93655693 

另外,当我把C中的权力结果存储在一个Javascript数字中时:

 > 8727963568087711970669458465954849888403456.0 8.727963568087712e+42 

注意差别 – > 8.727963568087713e+42 !== 8.727963568087712e+42 ,可以理解的是,模运算不能产生相同的结果。

我已经看了一下v8的Math.pow实现的源码,但是masmmacros看起来像是希腊语。

任何帮助在这里表示赞赏。

ECMAScript(“JavaScript”)对pow函数的精度没有任何保证。 ECMA-262说 :

返回一个依赖于实现的逼近来将x提升到y的结果。

C语言也不行。 只有C99规范的可选附件F是指IEC 60559(与IEEE 754相同),但是pow不是有精确保证的基本操作之一。

在你的情况下,从Node.js得到的结果比C程序的结果略微不准确,但是这并不违反规范。 你只需要忍受这种差异。 调用巨大的浮点数fmod是愚蠢的。

编辑:差异的原因可能是x87 80位“双扩展”格式的超额精度。 采取以下scheme:

 #include <stdio.h> #include <stdlib.h> #include <math.h> int main(int argc, char *argv[]) { int base = atoi(argv[1]); int exp = atoi(argv[2]); printf("pow: %.15e\n", pow(base, exp)); return 0; } 

用gcc编译,没有特别的select:

 $ gcc -Wall -O2 pow.c -lm -o pow $ ./pow 729 15 pow: 8.727963568087712e+42 

-mpc64编译:

 $ gcc -mpc64 -Wall -O2 pow.c -lm -o pow $ ./pow 729 15 pow: 8.727963568087713e+42