JavaScript中的计算结果与Java不同

Cap*_*ous 3 javascript java math

我认为我的问题很多.

Java中的计算:

int n = 4451 + 554 * 57;
n = n << 13 ^ n;
System.out.println(n * (n * n * 15731 + 789221) + 1376312589);
=> 587046333
Run Code Online (Sandbox Code Playgroud)

在JavaScript中:

var n = 4451 + 554 * 57;
n = n << 13 ^ n;
console.log(n * (n * n * 15731 + 789221) + 1376312589);
=> 4.043454188561781e+29
Run Code Online (Sandbox Code Playgroud)

JavaScript版本中的问题是什么?如何修复它,以便JavaScript的结果与Java结果相同?

编辑:试过:https://github.com/jtobey/javascript-bignum,但结果是0

var test = new BigInteger(295120061).multiply( new BigInteger(295120061) 
                                      .multiply(new BigInteger(295120061)) 
                                      .multiply(new BigInteger(15731)) 
                                      .add(new BigInteger(789221)))
                                      .add(new BigInteger(1376312589));
Run Code Online (Sandbox Code Playgroud)

=> test = 0

ajb*_*ajb 5

JavaScript没有整数运算,所有数字都存储为64位浮点数(double在Java中).当JavaScript看到像<<或的位处理运算符时^,它会暂时将操作数转换为32位整数来执行算术运算,然后将它们转换回64位浮点数.因此,最后的乘法作为JavaScript中的浮点运算执行.在Java中,它仍然是一个整数运算.这段代码在Java中执行相同的操作(我现在已经测试过了,结果是一样的):

int n = 4451 + 554 * 57;
n = n << 13 ^ n;
double x = n;
System.out.println(x * (x * x * 15731 + 789221) + 1376312589);
Run Code Online (Sandbox Code Playgroud)

如果您希望JavaScript代码与Java相同,则需要一种执行乘法和加法的方法,其工作方式与Java溢出时的方式相同.也就是说,它必须将所有操作的结果视为-2 31和2 31 -1.在JavaScript中使用其本机算法确实没有可靠的方法来实现这一点; 即使你给它两个只有31个有效位的值,当你乘以它们时你会得到62个有效位,而JavaScript的"数字"类型只有52位,这意味着一些位会丢失.可能有一个JavaScript库允许你做这种精确的整数运算,但我不是JavaScript框架的专家,所以我不知道那会是什么.也许别人会插话.