亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

為什么0.1+0.2不等于0.3

Profeel / 1229人閱讀

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

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

先看兩個(gè)簡(jiǎn)單但詭異的代碼:

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

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

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

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

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

這里以十進(jìn)制數(shù)13來(lái)展示“按位計(jì)數(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ì)算機(jī)內(nèi)部如何表示小數(shù)

再看小數(shù)怎么用按位計(jì)數(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ì)說(shuō),直接給出結(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取整過(guò)程:

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....。這是一個(gè)二進(jìn)制無(wú)限循環(huán)小數(shù),但計(jì)算機(jī)內(nèi)存有限,我們不能用儲(chǔ)存所有的小數(shù)位數(shù)。那么在精度與內(nèi)存間如何取舍呢?

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

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

0.1 + 0.1 為什么等于0.2

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

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

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

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

我們看兩個(gè)現(xiàn)實(shí)的場(chǎng)景:

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

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

不同行業(yè),要求的精度不是線性的,我們?cè)试S(對(duì)結(jié)果無(wú)關(guān)緊要的)誤差存在。10.0001與10.001在鐵路工程師看來(lái)都是合格的。

雖然允許誤差存在,但程序員在使用浮點(diǎn)數(shù)進(jìn)行計(jì)算或邏輯處理時(shí),不注意,就可能出問(wèn)題。記住,永遠(yuǎn)不要直接比較兩個(gè)浮點(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ù)計(jì)算

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

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

bignumber.js會(huì)在一定精度內(nèi),讓浮點(diǎn)數(shù)計(jì)算結(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ù)計(jì)算問(wèn)題,簡(jiǎn)單回答了為什么以及怎么辦兩個(gè)問(wèn)題:

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

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

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

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

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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/90020.html

相關(guān)文章

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

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

    bang590 評(píng)論0 收藏0
  • 什么JavaScript里面0.1+0.2 === 0.3是false

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

    nicercode 評(píng)論0 收藏0
  • javascript中0.1 + 0.2 != 0.3?

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

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

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

    張巨偉 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<