简体   繁体   English

为什么Java语言的Math.pow()与C语言中的相同,似乎返回一个四舍五入的值?

[英]Why does Javascript's Math.pow() seem to return a rounded value compared to the same in C?

My understanding is that both C's double and Javascript's numbers are IEEE 754 64 bit floating point numbers. 我的理解是C的double精度数和Javascript的数字都是IEEE 754 64位浮点数。 I am trying to port some code from C to Nodejs, and I am running into what appears to be a rounding error in Javascript's Math.pow() . 我试图将一些代码从C移植到Node.js,并且遇到了Javascript Math.pow()的舍入错误。

Here is my C program: 这是我的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); 
}

The output of which is: 输出为:

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

Interestingly, when I try to perform this calculation in Javascript (tested in node, Chrome, Firefox) 有趣的是,当我尝试使用Javascript执行此计算(在node,Chrome,Firefox中测试)

I get the following result: 我得到以下结果:

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

In addition, when I store the power result from C in a Javascript number: 另外,当我将C的幂结果存储在Javascript编号中时:

> 8727963568087711970669458465954849888403456.0
8.727963568087712e+42

Note the difference -> 8.727963568087713e+42 !== 8.727963568087712e+42 , so understandably the modulo operation fails to produce the same result. 注意差异-> 8.727963568087713e+42 !== 8.727963568087712e+42 ,因此可以理解,模运算不能产生相同的结果。

I've had a look at the source for v8's implementation of Math.pow, but the masm macros look like greek to me atm. 我看过v8实现Math.pow的源代码,但是masm宏对atm来说看起来像希腊文。

Any help here is appreciated. 感谢您的帮助。

ECMAScript ("JavaScript") doesn't make any guarantees about the precision of the pow function. ECMAScript(“ JavaScript”)对pow函数的精度不做任何保证。 ECMA-262 says : ECMA-262说

Returns an implementation-dependent approximation to the result of raising x to the power y. 返回将x提高到y的结果的依赖于实现的近似值。

Neither does the C language. C语言也没有。 Only the optional Annex F of the C99 spec refers to IEC 60559 (same as IEEE 754), but pow isn't one of the basic operations for which there are precision guarantees. 仅C99规范的可选附件F引用了IEC 60559(与IEEE 754相同),但是pow并不是具有精度保证的基本操作之一。

In your case, the result you get from Node.js is slighty more inaccurate than the result from your C program, but this doesn't violate the spec. 在您的情况下,从Node.js得到的结果比从C程序得到的结果稍微不准确,但这并不违反规范。 You simply have to live with this kind of differences. 您只需要忍受这种差异。 Calling fmod on huge floating point numbers is foolish anyway. 无论如何,在巨大的浮点数上调用fmod是愚蠢的。

Edit: The reason for the discrepancy is probably excess precision of the x87 80-bit "double extended" format. 编辑:差异的原因可能是x87 80位“双扩展”格式的精度过高。 Take the following program: 采取以下程序:

#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;
}

Compiled with gcc and no special options: 与gcc一起编译,没有特殊选项:

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

Compiled with -mpc64 : -mpc64编译:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM