2013-10-23 36 views
1

我最近發現了一個奇怪的JS代碼片段,但是我不確定它是一個bug還是有一些邏輯。Javascript編號獲得另一個值

試試這個數字:9000000022903136 * * 警告它,console.log它,將它分配給一個變量。您將獲得價值9000000022903136 * *。問題是爲什麼?它是一個錯誤?

我也注意到,你從90000000229031352得到​​90000000229031360到90000000229031368,爲90000000229031351你90000000229031340,爲90000000229031369你90000000229031369.

這發生在:鉻,FF,Node.js的

+1

JavaScript的商店*每*號的爲內部的浮動,包括整數。你只是失去了精確性。 – Blender

+0

有沒有辦法避免失去精確度? Java中是否有像BigInteger這樣的東西,或者更高精度的東西? –

+0

Google「bigint javascript」。沒有內置的東西。 – Blender

回答

3

好,計算機中的數字是有限的(大部分)。你在這裏看到的是一個浮點/雙重存儲號碼的經典溢出,它可以保存許多數字,並且它的指數(當然,實際實施方式不同):

123被存儲爲[1 2 3],指數2 1.23被存儲爲[1 2 3],指數0

所以,90000000229031368存儲爲:

[9 0 0 0 0 0 0 0 2 2 9 0 3 1 3 6],指數16.正如你所看到的,最後8位沒有空間了,所以當你讀時,它被設置爲

其他的例子似乎是矛盾的,但請記住,電腦沒有存儲在基地10這些數字,但基地2

瞭解更多關於這個問題,關鍵詞是:浮法浮點(例如,在維基百科上)。

+0

謝謝你的好解釋,我不知道JS中的整數不是真正的整數。 –

+0

@SilviuBurcea JS中沒有整數。有一個Number類型和它的IEEE 64位浮點(通常稱爲「IEEE double」)。有人建議將真正的整數類型添加到該語言中,或至少是真正的64位整數。 –

3

這是因爲javascript數字是64位浮點數。

浮點數有2個部分 - 小數部分定義數字的「值」,指數部分定義數字應該移動到小數點的左邊或右邊多遠。

爲了說明這一點的工作,我會使用的十進制基礎,而不是二進制的虛浮點數格式如何:

讓我們來定義我們想象的格式爲8個字符的花車 - 這是數必須存儲內8個字符。讓分區我們的格式,有6個字符作爲小數部分和2個字符作爲指數:

_ _ _ _ _ _ _ _ 
    |_ _|_ _ _ _ _ _| <--- 8 char float 
exponent fractional 

爲了便於討論,讓我們創造一個語法描述格式:

exponent,fractional 

因此,例如, ,號碼128可以存儲爲0,128,PI可以存儲爲-5,314159(小數點左移5位)。

上面的PI例子是程序員第一次遇到浮點數 - 他們需要使用分數而不是簡單的整數。但是浮點格式還有另外一個特點 - 它可以存儲大於分配小數部分空間的數字!

例如,如果我們想要以我們想象的8char浮點格式存儲數字987654321會怎麼樣?它超過6個字符!那麼,我們會這樣做:2,9876543。也就是說,我們存儲最重要的數字並將小數點右移2個空格。

如果我們嘗試讀取該數字,那麼得到的是987654300。我們失去了最低有效位數!嗯..聽起來很熟悉。

在javascript的情況下,格式是IEEE 754 64位二進制浮點。它有52位分配給小數部分(如果包含符號位,則爲53)。這意味着對於高達52位的數字,它的行爲就像一個整數。任何更大的,它將開始犧牲最不重要的位(不是數字,位,所以舍入可能對我們人類看起來很奇怪)。

詳情請參見在64位浮點數是如何工作的這個維基百科文章:http://en.wikipedia.org/wiki/Double_precision_floating-point_format