2014-11-22 17 views
3

我遇到了大量问题,我想。JavaScript中的计算结果不同于Java

Java中的计算:

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

在JavaScript:

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

什么是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)); 

=>测试= 0

+0

如果在Java示例中将'n'声明为'long',会发生什么? – ajb 2014-11-22 17:37:09

+0

然后我得到-1448455493533196867 – 2014-11-22 17:37:41

+0

尝试解析长解析int而不是隐式var – 2014-11-22 17:39:59

回答

3

的问题,如@ajb说,是JavaScript是弱类型,并进行双精确的浮点运算,而我们需要严格的32位整数运算。

对于乘法,为此存在函数Math.imul。它尚未在Internet Explorer中受支持,但链接的页面包含一个替代函数,该函数模拟旧版浏览器的imul,它通过分别将数字的上半部分和下半部分相乘来工作。

另外,我们可以用0或者OR来表示数字。这工作,因为任何位运算力的JavaScript数成为32位整数,并用0或运算实际上并没有改变超过该值:

Math.iadd = function(a, b) { return ((a|0) + (b|0))|0; } 

我们使用它:

var n = Math.iadd(4451, Math.imul(554, 57)); 
n = n << 13^n; 
console.log(Math.iadd(Math.imul(n, Math.iadd(Math.imul(Math.imul(n, n), 15731), 789221)), 1376312589)); 

一有点长和凌乱,但它的作品。输出是587046333,与Java相同。

+0

谢谢你,我upvoted,并会很快检查出来。那么额外的库可能会更高效 – 2014-11-23 16:58:08

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); 

如果你想JavaScript代码的工作方式相同的Java,您将需要执行乘法方式另外它的工作方式与Java在溢出时的工作方式相同。也就是说,它必须将所有操作的结果视为处于-2 和2 -1的范围内。使用其原生算法在JavaScript中确实没有可靠的方法;即使你给它两个只有31个有效位的值,当你乘以它们时,你将得到62个有效位,而JavaScript的“数字”类型只有52位,这意味着一些位会丢失。可能有一个JavaScript库,可以让你做这种精确的整数算术,但我不是JavaScript框架的专家,所以我不知道那会是什么。也许别人会附和

+0

您对此正确,现在它与JavaScript结果相同,但我需要另一种方式:)(javascript出来应该是587046333) – 2014-11-22 17:43:49

+0

@CaptainObvious我编辑了我的答案,但不幸的是它不会有太大的帮助。 – ajb 2014-11-22 17:51:25

+0

没问题,感谢其他信息反正;)我会试图找出我是否可以做到这一点,因为它对我的应用程序至关重要:) – 2014-11-22 17:52:31

1

使用:https://github.com/iriscouch/bigdecimal.js

var n = 4451 + 554 * 57; 
n=n << 13^n; 
var test = new BigDecimal(n).multiply(new BigDecimal(n) 
             .multiply(new BigDecimal(n)) 
             .multiply(new BigDecimal(15731)) 
             .add(new BigDecimal(789221))) 
             .add(new BigDecimal(1376312589)); 
    test.intValue() 

打印出正确的结果

+0

n33bs会n33b – 2015-02-02 20:03:40