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

資訊專(zhuān)欄INFORMATION COLUMN

浮點(diǎn)數(shù)那些事兒

Honwhy / 2406人閱讀

摘要:說(shuō)起浮點(diǎn)數(shù),大家都是又恨又愛(ài)的。當(dāng)小數(shù)不為時(shí),浮點(diǎn)數(shù)的值為,即不是一個(gè)數(shù)。所以,整個(gè)浮點(diǎn)數(shù)的二進(jìn)制表示就是。最后其實(shí),浮點(diǎn)數(shù)有很多坑。因此,我們?cè)谑褂酶↑c(diǎn)數(shù)的時(shí)候,一定要小心。還有,涉及到金額計(jì)算的時(shí)候,一定不能使用浮點(diǎn)數(shù)。

本文為作者自己的總結(jié)的,由于作者的水平限制,難免會(huì)有錯(cuò)誤,歡迎大家指正,感激不盡。

說(shuō)起浮點(diǎn)數(shù),大家都是又恨又愛(ài)的。愛(ài)呢,是因?yàn)?,只有它可以方便地使用小?shù);恨呢,是因?yàn)樗⒉荒芫_地表示小數(shù)。

以 PHP 為例:floor((0.1 + 0.7) * 10) 這樣一個(gè)函數(shù)調(diào)用,根據(jù)數(shù)學(xué)老師死得晚原理,大家都能得出 8 這個(gè)結(jié)果??墒鞘聦?shí)上呢?它會(huì)返回 7。數(shù)學(xué)老師的棺材板。。。(╯‵□′)╯︵┻━┻

可是為什么會(huì)出現(xiàn)這種情況呢?這就要從浮點(diǎn)數(shù)的特性說(shuō)起了。

萬(wàn)物皆二進(jìn)制

我們都知道,在計(jì)算機(jī)中,一切的一切都是二進(jìn)制表示的。假設(shè)一個(gè) 4 字節(jié)整型的十進(jìn)制數(shù) 8,在大端表示的機(jī)器中,表示成 00000000 00000000 00000000 000010000x0000008)。將十進(jìn)制整數(shù)轉(zhuǎn)換成二進(jìn)制數(shù),是非常容易的??墒牵?shù)呢?比如,我們要表示 1.75,該怎么存儲(chǔ)在計(jì)算機(jī)中呢?顯然,不能像整數(shù)一樣存儲(chǔ)了。

小數(shù)的二進(jìn)制

讓我們回憶一下,在十進(jìn)制中,小數(shù)是怎么計(jì)算的。上面的 1.75 我們是這么算的:1 × 10^0 + 7 × 10^-1 + 5 × 10^-2 。那么我們按照相同的規(guī)則,來(lái)用二進(jìn)制計(jì)算一下小數(shù)部分:0.75 = 1/2 + 1/4,也就是 1 × 2^-1 + 1 × 2^-2 ,再加上前面的整數(shù)部分,那么整個(gè)式子就變成了 1 × 2^0 + 1 × 2^-1 + 1 × 2^-2 ,寫(xiě)成二進(jìn)制形式就是 1.11。所以,1.75 的二進(jìn)制表示是 1.11。

對(duì)于將小數(shù)轉(zhuǎn)換為二進(jìn)制,和整數(shù)部分除二取余相反的,是乘二取整。

0.75 * 2 = 1.5 -> 1
0.5 * 2 = 1 -> 1

所以我們同樣可以得出 1.11。

科學(xué)計(jì)數(shù)法

好了,我們已經(jīng)知道如何表示一個(gè)小數(shù)的二進(jìn)制了。辣么,問(wèn)題來(lái)了。學(xué)過(guò) C 語(yǔ)言的同學(xué)都知道,一個(gè) float 只有 4 字節(jié),一個(gè) double 也只有 8 字節(jié)。那么,這么表示一個(gè)小數(shù),好像范圍很有限。

在數(shù)學(xué)老師哭暈在廁所之前,我們應(yīng)該還記得十進(jìn)制數(shù)中有這么一個(gè)東西——科學(xué)計(jì)數(shù)法,我們可以很方便地用它來(lái)表示很大的十進(jìn)制數(shù)。那么,同理,我們也可以用在浮點(diǎn)數(shù)的表示上。

讓我們先來(lái)回憶一下,科學(xué)計(jì)數(shù)法的表示。假設(shè)我們有一個(gè)數(shù) 17500,我們可以用科學(xué)計(jì)數(shù)法表示成 1.75 × 10^4 。我們照葫蘆畫(huà)瓢,在二進(jìn)制數(shù)中,假設(shè)有一個(gè)數(shù)是 11010。我們來(lái)和十進(jìn)制對(duì)應(yīng)一下。十進(jìn)制是乘 10,那么二進(jìn)制就是乘 2,我們對(duì)應(yīng)的就可以寫(xiě)成 1.101 × 2^100 。對(duì),其實(shí)就是這么簡(jiǎn)單。那也許有的人會(huì)問(wèn)了,為什么不寫(xiě)成 0.1101 × 2^101 呢?我們?cè)賮?lái)回憶一下,在十進(jìn)制科學(xué)計(jì)數(shù)法中,是不是有一個(gè)規(guī)定,整數(shù)部分的范圍是 [1,10)。那對(duì)應(yīng)到我們的二進(jìn)制數(shù)上,這個(gè)規(guī)定就可以變成 [1,2) 了,沒(méi)錯(cuò),對(duì)應(yīng)關(guān)系就是這么簡(jiǎn)單。

浮點(diǎn)數(shù)

好了,我們現(xiàn)在也知道怎么使用二進(jìn)制來(lái)表示小數(shù),以及使用科學(xué)計(jì)數(shù)法來(lái)表示二進(jìn)制小數(shù)了。那么,我們距離把數(shù)字存入計(jì)算機(jī)內(nèi)存僅剩一步之遙了,我們要把所有的東西存到內(nèi)存里去,那么我們就需要合理地分配內(nèi)存空間。浮點(diǎn)數(shù)有兩種,一種是單精度浮點(diǎn)數(shù)(float),占用 4 字節(jié)的內(nèi)存。其中,1 位是符號(hào)位,8 位是階碼(冪),23 位是尾數(shù)(小數(shù)部分)。

細(xì)心的各位可能會(huì)發(fā)現(xiàn),好像沒(méi)有整數(shù)部分?別急,這就是上面那個(gè)規(guī)定的有用之處。當(dāng)整數(shù)部分在 [1,2) 之間時(shí),也就只可能取到一個(gè)值 1,那么,對(duì)于這個(gè)值,我們是不是就可以當(dāng)做默認(rèn)值而不記錄在浮點(diǎn)數(shù)的表示中了?而這樣,我們的浮點(diǎn)數(shù)的精度又多了一位(小數(shù)部分的位數(shù)決定了精度)。這種表示叫做隱含 1 開(kāi)頭的表示。

規(guī)格化與非規(guī)格化 偏置值

到了這里,我們發(fā)現(xiàn),第一位是浮點(diǎn)數(shù)的正負(fù)符號(hào),那么,對(duì)于一個(gè)科學(xué)計(jì)數(shù)法來(lái)說(shuō),階碼同樣需要有正負(fù)。而在單精度中,階碼只有 8 位;雙精度中,階碼只有 11 位。如果我們給階碼表示成補(bǔ)碼,那么,我們能夠表示的數(shù)的范圍就會(huì)縮小,這樣顯然是不劃算的。于是,偏置值就由此誕生了。

規(guī)格化的值(階碼不全為 0 或 1)

在內(nèi)存中的規(guī)格化的浮點(diǎn)數(shù)表示中,階碼并非是 2 的冪,而是經(jīng)過(guò)計(jì)算的結(jié)果,這個(gè)計(jì)算公式就是 e - Bias,這里的 Bias 就是偏置值,而 e 就是階碼在浮點(diǎn)數(shù)中的二進(jìn)制表示。Bias 的值是 2^k-1 - 1(單精度是 127,雙精度是 1023),所以,e - Bias 的取值范圍就是 [-126, 127](單精度)和 [-1022, 1023](雙精度)。其實(shí)如果對(duì)補(bǔ)碼了解的比較好的同學(xué),應(yīng)該就能看出來(lái),這其實(shí)就是省略了符號(hào)位的補(bǔ)碼表示)。

通過(guò)上面的隱含 1 開(kāi)頭的表示的尾數(shù),我們可以計(jì)算出基數(shù) M = 1 + f。那么我們整個(gè)的浮點(diǎn)數(shù)可以寫(xiě)成這樣一個(gè)表達(dá)式:M × (e - Bias)。

非規(guī)格化的值(階碼全為 0)

對(duì)于規(guī)格化和非規(guī)格化的值來(lái)說(shuō),我們都可以用同一個(gè)式子來(lái)表示。不過(guò),為了某些更加方便的原因(這里就不展開(kāi)講了),對(duì)它們做了區(qū)分。如果按照規(guī)格化的計(jì)算來(lái)看,階碼的值是 0 - Bias,不過(guò)在這里,我們讓階碼的值等于 1 - Bias。同樣的,由于我們給階碼加了 1,那么整個(gè)浮點(diǎn)數(shù)就會(huì)向左移動(dòng)一位,那么,我們需要讓浮點(diǎn)數(shù)的值不變,M 就不在需要上面整數(shù)部分的 1 了,所以 M = f。

同時(shí),我們會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,那就是 +0.0 和 -0.0 在浮點(diǎn)數(shù)的二進(jìn)制表示上是不同的。

特殊值(階碼全為 1)

最后,還剩下這樣一種數(shù)字,那就是階碼全為 1 的情況。當(dāng)小數(shù)為 0 的時(shí)候,浮點(diǎn)數(shù)的值為 ∞。當(dāng)小數(shù)不為 0 時(shí),浮點(diǎn)數(shù)的值為 NaN,即不是一個(gè)數(shù)(Not a Number)。

計(jì)算浮點(diǎn)數(shù)

好了,扯了這么多,我們現(xiàn)在回到最開(kāi)始的問(wèn)題上,floor((0.1 + 0.7) * 10) = 7。我們先看 0.1 的二進(jìn)制表示。

首先,我們將十進(jìn)制小數(shù)轉(zhuǎn)換成二進(jìn)制小數(shù),可以得到 0.000[1100]···。讓我們轉(zhuǎn)換成浮點(diǎn)數(shù)的二進(jìn)制表示。按照上面的規(guī)則,它可以被表示成科學(xué)計(jì)數(shù)法 1.10011001100110011001100 × 2^-4 ,這樣,階碼就是 -4 + 127 = 123,二進(jìn)制表示為 01111011。所以,整個(gè)浮點(diǎn)數(shù)的二進(jìn)制表示就是 00111101110011001100110011001100(0x3dcccccc)。同樣的,0.7 會(huì)表示為00111101001100110011001100110011(0x3d333333)。

首先我們要對(duì)階碼小的數(shù)進(jìn)行對(duì)階,然后再進(jìn)行尾數(shù)的加法,這樣,我們得到的值就是 00111101111001100110011001100101。我們將其轉(zhuǎn)換成十進(jìn)制,發(fā)現(xiàn),它是小于 0.8 的。因此,當(dāng)我們?cè)龠M(jìn)行乘法運(yùn)算向下取整時(shí),會(huì)等于 7。

最后

其實(shí),浮點(diǎn)數(shù)有很多坑。因此,我們?cè)谑褂酶↑c(diǎn)數(shù)的時(shí)候,一定要小心。還有,涉及到金額計(jì)算的時(shí)候,一定不能使用浮點(diǎn)數(shù)。

本文為作者自己讀書(shū)總結(jié)的文章,由于作者的水平限制,難免會(huì)有錯(cuò)誤,歡迎大家指正,感激不盡。

參考文獻(xiàn)

《深入理解計(jì)算機(jī)系統(tǒng)(第 3 版)》第 2.4.2 節(jié)

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

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

相關(guān)文章

  • 點(diǎn)數(shù)那些事兒

    摘要:說(shuō)起浮點(diǎn)數(shù),大家都是又恨又愛(ài)的。當(dāng)小數(shù)不為時(shí),浮點(diǎn)數(shù)的值為,即不是一個(gè)數(shù)。所以,整個(gè)浮點(diǎn)數(shù)的二進(jìn)制表示就是。最后其實(shí),浮點(diǎn)數(shù)有很多坑。因此,我們?cè)谑褂酶↑c(diǎn)數(shù)的時(shí)候,一定要小心。還有,涉及到金額計(jì)算的時(shí)候,一定不能使用浮點(diǎn)數(shù)。 本文為作者自己的總結(jié)的,由于作者的水平限制,難免會(huì)有錯(cuò)誤,歡迎大家指正,感激不盡。 說(shuō)起浮點(diǎn)數(shù),大家都是又恨又愛(ài)的。愛(ài)呢,是因?yàn)?,只有它可以方便地使用小?shù);恨呢,...

    YFan 評(píng)論0 收藏0
  • JSON

    摘要:一直在用,發(fā)現(xiàn)并不了解。并且獨(dú)立于語(yǔ)言,可以在各語(yǔ)言間進(jìn)行數(shù)據(jù)交換。字符是大小敏感的。注意是轉(zhuǎn)義字符,還支持其他轉(zhuǎn)義字符,見(jiàn)參考數(shù)字可以整數(shù),浮點(diǎn)數(shù),科學(xué)計(jì)數(shù)法表示。元素類(lèi)型最好是同一類(lèi)型,畢竟大多數(shù)語(yǔ)言不支持元素類(lèi)型多種類(lèi)型。 一直在用JSON,發(fā)現(xiàn)并不了解JSON。好吧,花點(diǎn)時(shí)間學(xué)習(xí)下。 一、JSON的概念:什么是JSON? 全稱(chēng):JavaScript Object Natatio...

    Zhuxy 評(píng)論0 收藏0
  • 該死的IEEE-754點(diǎn)數(shù),說(shuō)「約」就「約」,你的底線呢?以JS的名義來(lái)好好查查你

    摘要:而的浮點(diǎn)數(shù)設(shè)置的偏移值是,因?yàn)橹笖?shù)域表現(xiàn)為一個(gè)非負(fù)數(shù),位,所以,實(shí)際的,所以。這是因?yàn)樗鼈冊(cè)谵D(zhuǎn)為二進(jìn)制時(shí)要舍入部分的不同可能造成的不同舍 IEEE 754 表示:你盡管抓狂、罵娘,但你能完全避開(kāi)我,算我輸。 一、IEEE-754浮點(diǎn)數(shù)捅出的那些婁子 首先我們還是來(lái)看幾個(gè)簡(jiǎn)單的問(wèn)題,能說(shuō)出每一個(gè)問(wèn)題的細(xì)節(jié)的話就可以跳過(guò)了,而如果只能泛泛說(shuō)一句因?yàn)镮EEE754浮點(diǎn)數(shù)精度問(wèn)題,那么下文還是...

    gaosboy 評(píng)論0 收藏0

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

0條評(píng)論

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