为什么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