2014-11-22 15 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