按照正常思維輸出58 ,但是運(yùn)行結(jié)果是57,然后在嘗試
intval(0.68*100)輸出 68
intval(0.56*100)輸出 56
intval(0.57*100)輸出 56
intval(0.58*100)輸出 57
intval(0.59*100)輸出 59
為什么只是0.57*100和0.58*100會(huì)特殊呢?
首先我們來(lái)看intval()在PHP 的 Manual 里有寫,是 intval() 這個(gè)函數(shù)的問(wèn)題,采用的是“截?cái)唷狈ㄈ≌?/p>
這個(gè)問(wèn)題看似奇特,其實(shí)還是浮點(diǎn)數(shù)的精度的問(wèn)題,0.58*100?的結(jié)果是什么?其實(shí)大家試試就知道了,并不是想象中的 58,而是?57.99999999999999,為什么會(huì)這樣 我們先來(lái)說(shuō)下計(jì)算機(jī)中保存浮點(diǎn)數(shù)?不能精確表示,本篇可能比較燒腦子,我會(huì)盡量用最通俗的語(yǔ)言,最貼近現(xiàn)實(shí)的例子來(lái)講解,不在乎篇幅有多長(zhǎng),關(guān)鍵是要給大家講明白。下一篇,你將了解到浮點(diǎn)數(shù)如何工作,以及為什么很多數(shù)?不能表示。
熱身?—— 問(wèn):要把小數(shù)裝入計(jì)算機(jī),總共分幾步?你猜對(duì)了,3 步。
? 第一步:轉(zhuǎn)換成二進(jìn)制
? 第二步:用二進(jìn)制科學(xué)計(jì)算法表示
? 第三步:表示成 IEEE 754 形式
在上面的第一步和第三步都有可能?丟失精度。
下面我們討論如何把十進(jìn)制小數(shù)轉(zhuǎn)換成二進(jìn)制小數(shù)(什么?你不會(huì)?請(qǐng)自覺(jué)去面壁)。考慮我們將 1/7(七分之一) 寫成小數(shù)的時(shí)候是如何做的?用 1 除以 7,得到的商就是小數(shù)部分,剩下的余數(shù)我們繼續(xù)除以 7,一直除到什么時(shí)候結(jié)束呢? 有兩種情況:
1. 如果余數(shù)為 0。yeah!終于結(jié)束了,洗洗睡吧
2. 當(dāng)除到某一步時(shí),余數(shù)等于 1… 停!stop!等一下,我發(fā)現(xiàn)有什么地方怪怪的。余數(shù)為 1,余數(shù)如果為 1 的話,再繼續(xù)除下去,不就又是 1/7 了嗎?繞了一個(gè)大彎,又回來(lái)了?對(duì),你猜的很對(duì),它永遠(yuǎn)不會(huì)結(jié)束,它循環(huán)了。注意我上面說(shuō)的 情況2,我們判斷他循環(huán),并?不是從直觀看感覺(jué)它重復(fù)了,而是因?yàn)樵谟?jì)算過(guò)程中,它又回到了開(kāi)頭。為什么這么說(shuō)呢?當(dāng)你計(jì)算一個(gè)分?jǐn)?shù)時(shí),它總是連續(xù)出現(xiàn) 5,出現(xiàn)了好多次,例如 0.5555555… 你也無(wú)法斷定它是無(wú)限循環(huán)的,比如 一億分之五
其實(shí) 0.58*100 = 57.99999999999999 是不局限于任何語(yǔ)言的,是 IEEE 規(guī)定的浮點(diǎn)數(shù)的運(yùn)算標(biāo)準(zhǔn)。一般情況下,57.99999999999999 會(huì)四舍五入到 58。需要注意的是,浮點(diǎn)數(shù)的四舍五入和咱們普通的數(shù)學(xué)里面的也是不同的,浮點(diǎn)數(shù)遇到 5 后,不一定總是入,有時(shí)也舍。
為什么結(jié)果是 57 呢,主要是因?yàn)?intval 函數(shù)的規(guī)則是,從第一個(gè)數(shù)字開(kāi)始,直到遇到不是數(shù)字的字符,結(jié)束。