將0.1累加100次也得不到10
我們來(lái)一個(gè)計(jì)算機(jī)運(yùn)算錯(cuò)誤的例子。
function sum(){
let sum = 0;
for(let i=1;i<=100;i++){
sum +=0.1;
}
console.log(sum)
}
我們?cè)跒g覽器的控制臺(tái)中,運(yùn)行sum()
,得到的運(yùn)行結(jié)果為9.99999999999998
。這顯然和我們的九年義務(wù)教育所教導(dǎo)的 「背道而馳」 。
有句話說(shuō), 「雪崩的時(shí)候,沒(méi)有一片雪花是無(wú)辜的」 。在這段代碼中,程序沒(méi)錯(cuò),計(jì)算機(jī)也沒(méi)有發(fā)生故障,當(dāng)然和所使用的語(yǔ)言也沒(méi)有關(guān)系(選用其他的高級(jí)語(yǔ)言可能運(yùn)算結(jié)果不同)。如果硬要找一個(gè)背鍋的,那就是 「計(jì)算機(jī)處理小數(shù)的機(jī)制」 。
用二進(jìn)制數(shù)表示小數(shù)
在計(jì)算機(jī)底層知識(shí)之二進(jìn)制中我們講過(guò),由于計(jì)算機(jī)內(nèi)部所有的信息都是以二進(jìn)制數(shù)的形式來(lái)處理,因此, 「整數(shù)和小數(shù)并無(wú)差別」 。
在說(shuō)明計(jì)算機(jī)如何用二進(jìn)制數(shù)表示小數(shù)的具體方法前,我們先嘗試將1011.0011
這個(gè)有小數(shù)點(diǎn)的二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)。
小數(shù)點(diǎn) 「前面」 部分的轉(zhuǎn)換方法在計(jì)算機(jī)底層知識(shí)之二進(jìn)制中介紹過(guò)。只需將各 「數(shù)位」 數(shù)值和 「位權(quán)」 相乘,然后再將相乘的結(jié)果相加即可實(shí)現(xiàn)。其實(shí),針對(duì)小數(shù)點(diǎn)后面的部分,也是 「照貓畫虎」 ,也是將各 「數(shù)位」 數(shù)值和 「位權(quán)」 相乘的結(jié)果相加即可。
二進(jìn)制數(shù)小數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)
二進(jìn)制數(shù)小數(shù)點(diǎn)前面部分的**「位權(quán)」**
- 第一位是
2
的0
次冪 - 第二位是
2
的1
次冪 - 第三位是
2
的2
次冪 - 以此類推
而小數(shù)點(diǎn)后面部分的**「位權(quán)」**
- 第一位是
2
的-1
次冪 - 第二位是
2
的-2
次冪 - 第三位是
2
的-3
次冪 - 以此類推
?0次冪前面的位的位權(quán)按照
1
次冪、2
次冪····的方式**「遞增」**0次冪后面的位的位權(quán)按照
-1
次冪、-2
次冪····的方式**「遞減」**?
計(jì)算機(jī)運(yùn)算出錯(cuò)的原因
?計(jì)算機(jī)運(yùn)算出錯(cuò)的原因:「有一些十進(jìn)制數(shù)的小數(shù)無(wú)法轉(zhuǎn)換成二進(jìn)制」
?
小數(shù)點(diǎn)后4位用二進(jìn)制數(shù)表示時(shí)的數(shù)值范圍為0.0000~0.1111
。這里只能表示0.5
、0.24
、0.125
、0.0625
這四個(gè)二進(jìn)制數(shù)小數(shù)點(diǎn)后面的位權(quán)組合而成(相加總和)的小數(shù)。
?可以看出:「二進(jìn)制數(shù)是連續(xù)的,十進(jìn)制數(shù)是非連續(xù)的」
?
在前面講二進(jìn)制
的時(shí)候,我們說(shuō),根據(jù)IC
引腳個(gè)數(shù)不同,我們可以表示位數(shù)不同的二進(jìn)制數(shù)。我們可以通過(guò)增加引腳數(shù),也就是增加二進(jìn)制小數(shù)點(diǎn)后面的位數(shù),與其相對(duì)應(yīng)的十進(jìn)制數(shù)的個(gè)數(shù)也會(huì)增加, 「但是不管增加多少位,2的-〇〇
次冪怎么相加都無(wú)法得到0.1這個(gè)結(jié)果」 。
實(shí)際上,十進(jìn)制數(shù)0.1
轉(zhuǎn)換成二進(jìn)制后,會(huì)變成0.00011001100···
(1100
循環(huán))這樣的 「循環(huán)小數(shù)」 。這和用十進(jìn)制數(shù)來(lái)表示1/3
是一樣的道理。
?計(jì)算機(jī)這個(gè) 「功能有限」 的機(jī)器設(shè)備,是無(wú)法處理 「無(wú)限循環(huán)」 的小數(shù)的
?
因此,在遇到 「循環(huán)小數(shù)」 時(shí),計(jì)算機(jī)就會(huì)根據(jù) 「變量數(shù)據(jù)類型」 所對(duì)應(yīng)的長(zhǎng)度將數(shù)值從 「中間截?cái)唷?/strong> 或者 「四舍五入」 。
然后,我們?cè)俳Y(jié)合我們上面的例子,一個(gè) 「循環(huán)小數(shù)」 在進(jìn)行存儲(chǔ)的時(shí)候,已經(jīng)被 「掐頭去尾」 ,而偏偏針對(duì)這個(gè)值,又進(jìn)行了N
多次處理。不怕你不努力,就怕你,持之以恒的向偏離既定軌道的方向上移動(dòng),那么結(jié)果可想而知,是永遠(yuǎn)不會(huì)達(dá)到最終想要的結(jié)果。
浮點(diǎn)數(shù)
像1011.0011
這樣帶小數(shù)點(diǎn)的表現(xiàn)形式,在計(jì)算機(jī)內(nèi)部是無(wú)法使用的。
很多編程語(yǔ)言中都提供了兩種表示小數(shù)的數(shù)據(jù)類型,分別是 「雙精度浮點(diǎn)數(shù)」 和 「單精度浮點(diǎn)數(shù)」 。
- 「雙精度浮點(diǎn)數(shù)」 用
64
位表示小數(shù) - 「單精度浮點(diǎn)數(shù)」 用
32
位表示小數(shù)
「浮點(diǎn)數(shù)」 是指用 「符號(hào)」 、 「尾數(shù)」 、 「基數(shù)」 和 「指數(shù)」 這四部分表示的小數(shù)。
?計(jì)算機(jī)內(nèi)部使用的是二進(jìn)制數(shù),所以 「基數(shù)是2」 ,因此,實(shí)際的數(shù)據(jù)中往往不考慮基數(shù)。只用 「符號(hào)」 、 「尾數(shù)」 、 「指數(shù)」 這三部分就可以表示 「浮點(diǎn)數(shù)」 。
?
浮點(diǎn)數(shù)表現(xiàn)形式
浮點(diǎn)數(shù)的表現(xiàn)方式有很多中,我們采用IEEE標(biāo)準(zhǔn)
來(lái)解釋。
雙精度浮點(diǎn)數(shù)和單精度浮點(diǎn)數(shù)在表示同一個(gè)數(shù)值時(shí) 「使用的位數(shù)」 不同。
「符號(hào)部分」 是指使用一個(gè) 「數(shù)據(jù)位」 來(lái)表示符號(hào)。「數(shù)據(jù)位是1時(shí)表示負(fù),為0時(shí)表示正或者0」
?數(shù)值的大小用 「尾數(shù)部分」 和 「指數(shù)部分」 來(lái)表示。即用 「尾數(shù)部分 × 2的指數(shù)部分次冪」 的形式來(lái)表示。
?
- 「尾數(shù)部分」 用的是**「將小數(shù)點(diǎn)前面的值固定為1的正則表達(dá)式」**
- 「指數(shù)部分」 用的是**「EXCESS系統(tǒng)表示」**
-
計(jì)算機(jī)
+關(guān)注
關(guān)注
19文章
7295瀏覽量
87533 -
程序
+關(guān)注
關(guān)注
115文章
3749瀏覽量
80670 -
代碼
+關(guān)注
關(guān)注
30文章
4697瀏覽量
68091
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論