[點晴永久免費OA]關于 js 中的精度丟失問題
前言在 Javascript 中,由于采用了 IEEE 754 標準的浮點數(shù)表示方法,可能會導致精度丟失問題。這主要是因為浮點數(shù)在內(nèi)存中以二進制的形式存儲,而某些十進制數(shù)無法精確地轉(zhuǎn)換成二進制表示。當進行計算時,就會出現(xiàn)舍入誤差。 例如以下示例:
結(jié)果不精確是因為 0.1 和 0.2 無法用二進制無法精確地表示出來,進行運算時也會存在誤差。 本文將以此為例,從二進制轉(zhuǎn)化,存儲到計算來分析造成這一結(jié)果的根本原因,文章篇幅不多,希望看完后可以給你帶來一些收獲...... 如何轉(zhuǎn)化?首先我們要清楚整數(shù)和小數(shù)是如何轉(zhuǎn)化為二進制的。 整數(shù)部分:除2取余 + 逆序排列,示例如下: 8 / 2 = 4 ...... 0 4 / 2 = 2 ...... 0 2 / 2 = 1 ...... 0 1 / 2 = 0 ...... 1 整數(shù) 8 轉(zhuǎn)化為二進制的結(jié)果是: 小數(shù)部分:乘2取整 + 順序排列,示例如下: 0.1 * 2 = 0.2 ...... 0 0.2 * 2 = 0.4 ...... 0 0.4 * 2 = 0.8 ...... 0 0.8 * 2 = 1.6 ...... 1 0.6 * 2 = 1.2 ...... 1 0.2 * 2 = 0.4 ...... 0 ... 小數(shù) 0.1 轉(zhuǎn)化為二進制的結(jié)果是: 如何存儲?js 中 Number 類型使用 IEEE 754 標準 64 位存儲,為每個數(shù)值分配 64 位存儲空間,以科學計數(shù)法的方式進行存儲。形式如下: 1.xxxxxx * 2 ^ n 64位存儲空間分為3個部分,包括 符號位、指數(shù)位 和 小數(shù)位,如下圖所示:
符號位占 1 位,標記數(shù)值的正負, 指數(shù)位占 11 位,值為一個固定值 1023 (IEEE 754 標準) + 科學計數(shù)法中的指數(shù)值,再將其轉(zhuǎn)為 11 位二進制。比如 0.1 = 0.00011001... = 1.1001... * 2 ^ (-4),指數(shù)位就為 1023 + (-4) = 1019,用 11 位二進制表示為 小數(shù)位占 52 位,用來存放小數(shù)點后的數(shù)值,以 0.1 為例,由于小數(shù)位只能存儲 52 位,又因為第 53 位為 1,所以截取需要往前進一位再保存,這里就造成了第一次的精度丟失。 相同的道理,所以 0.1 和 0.2 在內(nèi)存中就是這樣的:
如何計算?最后就是將 64 位雙精度浮點數(shù)相加,首先我們把偏移量還原對齊,再進行相加,如下圖所示:
相加后發(fā)現(xiàn)小數(shù)部分有 53 位,由于小數(shù)位只能存儲 52 位,因此需要再次進行截取,這里就造成了第二次的精度丟失。將這個結(jié)果轉(zhuǎn)化為十進制就得到了一開始我們打印的結(jié)果。 這也就是為什么 0.1 + 0.2 不等于 0.3 的原因。 解決方法可以使用一些第三方庫來解決,例如: 總結(jié)
該文章在 2023/6/26 11:32:06 編輯過 |
關鍵字查詢
相關文章
正在查詢... |