簡體   English   中英

JavaScript 中的浮點數 (IEEE 754)

[英]Floating point number in JavaScript (IEEE 754)

在此處輸入圖片說明

如果我理解正確的話,JavaScript 數字總是按照國際 IEEE 754 標准存儲為雙精度浮點數。 這意味着它使用 52 位作為小數有效數。 但是在上圖中,二進制中的 0.57 似乎使用了 54 位。

另一件事是(如果我理解正確的話)二進制 0.55 也是一個重復數字。 但是為什么0.55 + 1 = 1.55 (沒有損失)和0.57 + 1 = 1.5699999999999998

4"

這意味着它使用 52 位作為小數有效數。 但是在上圖中,二進制中的 0.57 似乎使用了 54 位。

JavaScript 的Number類型本質上是 IEEE 754 基本 64 位二進制浮點數,具有 53 位有效數。 52 位編碼在“尾隨有效數”字段中。 前導位通過指數字段編碼(1-2046 的指數字段表示前導位為 1,指數字段 0 表示前導位為零,2047 的指數字段用於無窮大或 NaN)。

您看到的 0.57 的值有 53 個有效位。 領先的“0”。 toString操作產生; 它不是數字編碼的一部分。

但是為什么 0.55 + 1 = 1.55(沒有損失)和 0.57 + 1 = 1.5699999999999998。

當 JavaScript 格式化一些Number x以使用其默認規則顯示時,這些規則說產生最短的十進制數字(在其有效數字中,不計算像前導“0”這樣的裝飾。)當轉換回Number格式時,產生x 此規則的目的包括 (a) 始終確保顯示唯一標識哪個確切的Number值是源值,以及 (b) 不使用超過完成 (a) 所需的數字。

因此,如果您以十進制數字(如 .57)開始並將其轉換為Number ,您將得到一些值x ,這是轉換必須四舍五入為可以用Number格式表示的Number 然后,當x被格式化以供顯示時,您將獲得原始數字,因為產生最短數字並轉換回x 的規則自然會產生您開始使用的數字。

(但那個x並不完全代表 0.57。最接近 0.57 的double 精度略低於它; 在 IEEE double精度計算器上查看它的十進制和二進制 64 表示)。

另一方面,當您執行諸如.57 + 1類的某些操作時,您正在執行一些算術運算,該算術生成的數字y並非以簡單的十進制數字開頭。 因此,在格式化此類數字以供顯示時,規則可能需要使用更多數字。 換句話說。 當您將.571相加時, Number格式的結果與您從1.57得到的數字不同。 因此,要格式化.57 + 1的結果,JavaScript 必須使用更多數字來區分該數字與您從1.57獲得的數字——它們是不同的,必須以不同的方式顯示。


如果 0.57 完全可以表示為double ,則總和的預舍入結果將正好是 1.57,因此1 + 0.57將舍入為與1.57相同的double

但事實並非如此,實際上是1 + nearest_double(0.57) =
1.569999999999999951150186916493 (四舍五入,不是double 1.569999999999999951150186916493 ),四舍五入為
1.56999999999999984012788445398 這些數字的十進制表示比我們需要區分有效數的 1ulp(最后一位單位),甚至 0.5 ulp 最大舍入誤差所需的位數多得多。

1.57 舍入到 ~ 1.57000000000000006217248937901 ,因此這不是打印1 + 0.57的結果的選項。 十進制字符串需要將數字與相鄰的 binary64 值區分開來。


碰巧發生在.55 + 1中的舍入產生與從1.55轉換為Number相同的數字,因此顯示.55 + 1的結果會產生“1.55”。

toString(2)字符串打印到最后一個非零數字。

1.57 與 1 + 0.57 具有不同的位表示(但得到結果 1.57 並非不可能),
但是二進制中的 1 + 0.55 等於 1.55,如下面的代碼片段所示:

 console.log(1.57) console.log(1.57.toString(2)) console.log((1+.57).toString(2)) console.log("1.32 + 0.25 = ",1.32 + .25) console.log((1.32 + .25).toString(2)) console.log(1.55) console.log(1.55.toString(2)) console.log((1+.55).toString(2))

請記住,計算機對二進制數執行操作, 1.571.55只是人類可讀的輸出

Number.prototype.toString大致實現了 ES262 規范的以下部分:

7.1.12.1 NumberToString(m)

令 n、k 和 s 是整數,使得 k ≥ 1, 10 ** k-1 ≤ s < 10 ** k,

s × 10 ** nk 的數值是 m,

並且 k 盡可能小。

因此toString只是估計值,它不返回存儲的確切字節。

您在控制台中看到的也不是准確的表示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM