成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

為什么0.1+0.2不等于0.3

Profeel / 1186人閱讀

摘要:又如,對于,結(jié)果其實并不是,但是最接近真實結(jié)果的數(shù),比其它任何浮點(diǎn)數(shù)都更接近。許多語言也就直接顯示結(jié)果為了,而不展示一個浮點(diǎn)數(shù)的真實結(jié)果了。小結(jié)本文主要介紹了浮點(diǎn)數(shù)計算問題,簡單回答了為什么以及怎么辦兩個問題為什么不等于。

原文地址:為什么0.1+0.2不等于0.3

先看兩個簡單但詭異的代碼:

0.1 + 0.2 > 0.3 // true
0.1 * 0.1 = 0.010000000000000002

0.1加0.2為什么就不等于0.3昵?要回答這個問題,得先了解計算機(jī)內(nèi)部是如何表示數(shù)的。

計算機(jī)內(nèi)部如何表示數(shù)

我們都知道,計算機(jī)用位來儲存及處理數(shù)據(jù)。每一個二進(jìn)制數(shù)(二進(jìn)制串)都一一對應(yīng)一個十進(jìn)制數(shù)。

1. 計算機(jī)內(nèi)部如何表示整數(shù)

這里以十進(jìn)制數(shù)13來展示“按位計數(shù)法”如何表示整數(shù):

十進(jìn)制值 進(jìn)制 按位格式 描述
13 10 13 1x10^1 + 3x10^0 = 10 + 3
13 2 1101 1x2^3 + 1x2^2 + 0x2^1 + 1x2^0 = 8 + 4 + 0 + 1
2. 計算機(jī)內(nèi)部如何表示小數(shù)

再看小數(shù)怎么用按位計數(shù)法表示,以十進(jìn)制數(shù)0.625為例:

十進(jìn)制值 進(jìn)制 按位格式 描述
0.625 10 0.625 6x10^-1 + 2x10^-2 + 5x10^-3 = 0.6 + 0.02 + 0.005
0.625 2 0.101 1x2^-1 + 0 x2^-2 + 1x2^-3 = 1/2 + 0 + 1/8
3. 如何用二進(jìn)制表示0.1

關(guān)于十進(jìn)制與二進(jìn)制間如何轉(zhuǎn)換,這里不細(xì)說,直接給出結(jié)論:

十進(jìn)制整數(shù)轉(zhuǎn)二進(jìn)制方法:除2取余;十進(jìn)制小數(shù)轉(zhuǎn)二進(jìn)制方法:乘2除整

十進(jìn)制0.1轉(zhuǎn)換成二進(jìn)制,乘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

.....

從上面可以看出,0.1的二進(jìn)制格式是:0.0001100011....。這是一個二進(jìn)制無限循環(huán)小數(shù),但計算機(jī)內(nèi)存有限,我們不能用儲存所有的小數(shù)位數(shù)。那么在精度與內(nèi)存間如何取舍呢?

答案是:在某個精度點(diǎn)直接舍棄。當(dāng)然,代價就是,0.1在計算機(jī)內(nèi)部根本就不是精確的0.1,而是一個有舍入誤差的0.1。當(dāng)代碼被編譯或解釋后,0.1已經(jīng)被四舍五入成一個與之很接近的計算機(jī)內(nèi)部數(shù)字,以至于計算還沒開始,一個很小的舍入錯誤就已經(jīng)產(chǎn)生了。這也就是 0.1 + 0.2 不等于0.3 的原因。

有誤差的兩個數(shù),其計算的結(jié)果,當(dāng)然就很可能與我們期望的不一樣了。注意前面的這句話中的“很可能”這三個字?為啥是很可能昵?

0.1 + 0.1 為什么等于0.2

答案是:兩個有舍入誤差的值在求和時,相互抵消了,但這種“負(fù)負(fù)得正,相互抵消”不一定是可靠的,當(dāng)這兩個數(shù)字是用不同長度數(shù)位來表示的浮點(diǎn)數(shù)時,舍入誤差可能不會相互抵消。

又如,對于 0.1 + 0.3 ,結(jié)果其實并不是0.4,但0.4是最接近真實結(jié)果的數(shù),比其它任何浮點(diǎn)數(shù)都更接近。許多語言也就直接顯示結(jié)果為0.4了,而不展示一個浮點(diǎn)數(shù)的真實結(jié)果了。

另外要注意,二進(jìn)制能精確地表示位數(shù)有限且分母是2的倍數(shù)的小數(shù),比如0.5,0.5在計算機(jī)內(nèi)部就沒有舍入誤差。所以0.5 + 0.5 === 1

計算機(jī)這樣胡亂舍入,能滿足所有的計算需求嗎

我們看兩個現(xiàn)實的場景:

對于一個修建鐵路的工程師而言,10米寬,還是10.0001米寬并沒有什么不同。鐵路工程師就不需要這么高0.x這樣的精度

對于芯片設(shè)計師,0.0001米就會是一個巨大不同,他也永遠(yuǎn)不用處理超過0.1米距離

不同行業(yè),要求的精度不是線性的,我們允許(對結(jié)果無關(guān)緊要的)誤差存在。10.0001與10.001在鐵路工程師看來都是合格的。

雖然允許誤差存在,但程序員在使用浮點(diǎn)數(shù)進(jìn)行計算或邏輯處理時,不注意,就可能出問題。記住,永遠(yuǎn)不要直接比較兩個浮點(diǎn)的大小

var a = 0.1
var b = 0.2

if (a + b === 0.3) {
  // doSomething
}
JS中如何進(jìn)入浮點(diǎn)數(shù)運(yùn)算
將浮點(diǎn)運(yùn)算轉(zhuǎn)換成整數(shù)計算

整數(shù)是完全精度的,不存在舍入誤差。例如,一些關(guān)于人民幣的運(yùn)算,都會以分為基本單位,計算采用分,展示再轉(zhuǎn)換成元。當(dāng)然,這樣也有一些問題,會帶來額外的工作量,如果那天人民幣新增了一個貨幣單位,對系統(tǒng)的擴(kuò)展性也會有考驗。

使用bignumber進(jìn)行運(yùn)算

bignumber.js會在一定精度內(nèi),讓浮點(diǎn)數(shù)計算結(jié)果符合我們的期望。

{
  let x = new BigNumber(0.1);
  let y = new BigNumber(0.2)
  let z = new BigNumber(0.3)

  console.log(z.equals(x.add(y))) // 0.3 === 0.1 + 0.2, true
  console.log(z.minus(x).equals(y)) // true
  console.log(z.minus(y).equals(x)) // true
}
{
  let x = 0.2
  console.log(x * x === 0.04) // false
  let y = new BigNumber(0.2)
  let r = y.mul(y) // 0.04
  console.log(r.equals(new BigNumber(0.04))) // true
}

更多例子,可以看bignumber.js官方示例。

小結(jié)

本文主要介紹了浮點(diǎn)數(shù)計算問題,簡單回答了為什么以及怎么辦兩個問題:

為什么0.1 + 0.2 不等于0.3。因為計算機(jī)不能精確表示0.1, 0.2這樣的浮點(diǎn)數(shù),計算時使用的是帶有舍入誤差的數(shù)

并不是所有的浮點(diǎn)數(shù)在計算機(jī)內(nèi)部都存在舍入誤差,比如0.5就沒有舍入誤差

具有舍入誤差的運(yùn)算結(jié)可能會符合我們的期望,原因可能是“負(fù)負(fù)得正”

怎么辦?1個辦法是使用整型代替浮點(diǎn)數(shù)計算;2是不要直接比較兩個浮點(diǎn)數(shù),而應(yīng)該使用bignumber.js這樣的浮點(diǎn)數(shù)運(yùn)算庫

最后,本文只是簡單回答了為什么,如果讀者對更根本深入的原理感興趣,可以自行g(shù)oogle之。限于水平有限,本文如果有錯誤,歡迎指正。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90020.html

相關(guān)文章

  • JS中如何理解浮點(diǎn)數(shù)?

    摘要:本文通過介紹的二進(jìn)制存儲標(biāo)準(zhǔn)來理解浮點(diǎn)數(shù)運(yùn)算精度問題,和理解對象的等屬性值是如何取值的,最后介紹了一些常用的浮點(diǎn)數(shù)精度運(yùn)算解決方案。浮點(diǎn)數(shù)精度運(yùn)算解決方案關(guān)于浮點(diǎn)數(shù)運(yùn)算精度丟失的問題,不同場景可以有不同的解決方案。 本文由云+社區(qū)發(fā)表 相信大家在平常的 JavaScript 開發(fā)中,都有遇到過浮點(diǎn)數(shù)運(yùn)算精度誤差的問題,比如 console.log(0.1+0.2===0.3)// fa...

    bang590 評論0 收藏0
  • 什么JavaScript里面0.1+0.2 === 0.3是false

    摘要:返回是,這是為什么呢我們知道浮點(diǎn)數(shù)計算是不精確的,上面的返回式實際上是這樣的在的新規(guī)范加入了一個新的東西是在對象上面,新增一個極小的常量。根據(jù)規(guī)格,它表示與大于的最小浮點(diǎn)數(shù)之間的差。上面的代碼為浮點(diǎn)數(shù)運(yùn)算,部署了一個誤差檢查函數(shù)。 0.1+0.2 === 0.3 //返回是false, 這是為什么呢?? 我們知道浮點(diǎn)數(shù)計算是不精確的,上面的返回式實際上是這樣的:0.1 + 0.2 = ...

    nicercode 評論0 收藏0
  • javascript中0.1 + 0.2 != 0.3?

    摘要:按照的數(shù)字格式,整數(shù)有的范圍是,而且只能表示有限個浮點(diǎn)數(shù),能表示的個數(shù)為個。 0.1+0.2 等于0.3嗎?相信拿著這條題目隨便問一個高年級的小學(xué)生,他們都會毫不猶豫都回答:相等。是的,相等是正常的,這是常識。但是都說實踐是檢驗真理的唯一標(biāo)準(zhǔn),拿這道簡單的算術(shù)題用javascript在chrome控制臺試驗一下: 結(jié)果令人大跌眼鏡,在控制臺輸入0.1+0.2 == 0.3返回的結(jié)果竟然...

    ivydom 評論0 收藏0
  • 利用babel(AST)優(yōu)雅地解決0.1+0.2!=0.3的問題

    摘要:因此利用以及語法樹在代碼構(gòu)建過程中重寫等符號,開發(fā)時直接以這樣的形式編寫代碼,在構(gòu)建過程中編譯成,從而在開發(fā)人員無感知的情況下解決計算失精的問題,提升代碼的可讀性。 前言 你了解過0.1+0.2到底等于多少嗎?那0.1+0.7,0.8-0.2呢? 類似于這種問題現(xiàn)在已經(jīng)有了很多的解決方案,無論引入外部庫或者是自己定義計算函數(shù)最終的目的都是利用函數(shù)去代替計算。例如一個漲跌幅百分比的一個...

    張巨偉 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<