摘要:浮點(diǎn)數(shù)在計(jì)算機(jī)中是根據(jù)二進(jìn)制浮點(diǎn)數(shù)算數(shù)標(biāo)準(zhǔn)儲(chǔ)存的。尤其在我們?nèi)粘9ぷ髦?,不要比較浮點(diǎn)數(shù)的大小,如果需要精確的比較計(jì)算,請(qǐng)使用系列函數(shù)。還有一點(diǎn),浮點(diǎn)數(shù)不準(zhǔn)確和沒有任何關(guān)系,不背這個(gè)鍋。
奇怪的結(jié)果大家在日常開發(fā)中,必然使用過(guò)浮點(diǎn)數(shù),也會(huì)發(fā)現(xiàn)浮點(diǎn)數(shù)不是精確的,那究竟是什么原因造成的呢?
var_dump((1-0.9) == 0.1); //輸出:bool(false)
很奇怪吧!1-0.9怎么能不等于0.1呢?這是為什么呢?這要從浮點(diǎn)數(shù)的儲(chǔ)存標(biāo)準(zhǔn)開始說(shuō)。
IEEE 754浮點(diǎn)數(shù)在計(jì)算機(jī)中是根據(jù)IEEE 754(二進(jìn)制浮點(diǎn)數(shù)算數(shù)標(biāo)準(zhǔn))儲(chǔ)存的。
計(jì)算公式為: (-1)^S x M x 2^E
32位單精度儲(chǔ)存結(jié)構(gòu)(對(duì)應(yīng)占位)
符號(hào)(S) | 階碼(E) | 尾數(shù)(M) |
---|---|---|
1 | 8 | 23 |
64位雙精度儲(chǔ)存結(jié)構(gòu)(對(duì)應(yīng)占位)
符號(hào)(S) | 階碼(E) | 尾數(shù)(M) |
---|---|---|
1 | 11 | 52 |
解釋:
S: 符號(hào)(0正,1負(fù))
E: 階碼(指數(shù))
M: 尾數(shù)(二進(jìn)制小數(shù),數(shù)字的實(shí)體部分)
M(尾數(shù))和E(階碼)不同情況需要分別對(duì)待
E(階碼)的三種狀態(tài)及對(duì)應(yīng)的M表示從圖中(截圖于深入理解計(jì)算機(jī)系統(tǒng))我們可以分為三種情況(第三種又分為兩種特殊情況)
規(guī)格化E既不等于0也不等于255(將S按十進(jìn)制計(jì)算),這個(gè)時(shí)候的E=E-127,M的二進(jìn)制小數(shù)默認(rèn)省略了1.,也就是M=1.M(二進(jìn)制小數(shù))
我們做一個(gè)簡(jiǎn)單的測(cè)試看一下二進(jìn)制00111110001000000000000000000000(32位)表示的對(duì)應(yīng)的浮點(diǎn)數(shù)為多少?
首先拆分二進(jìn)制: 0 01111100 01000000000000000000000
E = 124 = 124 - 127 = -3
M = 1.01000000000000000000000
套公式: 1 x 1.01000000000000000000000 x 2^-3 = 0.00101000000000000000000000 = 2^-3 + 2^-5 = 0.15625
使用PHP驗(yàn)證一下結(jié)果:
var_dump(unpack("f", pack("l", bindec("00111110001000000000000000000000")))[1]); //輸出: float(0.15625)
上面的例子沒有丟失精度,下面看一個(gè)丟失精度的例子:
printf("%032s", decbin(unpack("l", pack("f", 1/3))[1])); //輸出: 00111110101010101010101010101011 var_dump(unpack("f", pack("l", bindec("00111110101010101010101010101011")))[1]); float(0.33333334326744)
丟失精度最主要原因就在于M(二進(jìn)制小數(shù)),我們只能精確的表示2^n倍數(shù)的數(shù)(2^-1(0.5),2^-2(0.25),2^-3(0.125)...),丟了在所難免。
非規(guī)格化E等于0,這個(gè)時(shí)候E=-126,M的二進(jìn)制小數(shù)前綴為0.,也就是M=0.M(二進(jìn)制小數(shù)),具體過(guò)程就不寫了,和上面類似
特殊情況E等于255(全部位都為1),如果M全部為0,那么表示為無(wú)窮大,否則表示為NaN(不是一個(gè)數(shù))
var_dump(unpack("f", pack("l", bindec("01111111100000000000000000000000")))[1]); //輸出: float(INF) var_dump(unpack("f", pack("l", bindec("01111111100000000000000000000110")))[1]); //輸出: float(NAN)不要比較浮點(diǎn)數(shù)
總之,浮點(diǎn)數(shù)是不準(zhǔn)確的。尤其在我們?nèi)粘9ぷ髦?,不要比較浮點(diǎn)數(shù)的大小,如果需要精確的比較計(jì)算,請(qǐng)使用bc*系列函數(shù)。
還有一點(diǎn),浮點(diǎn)數(shù)不準(zhǔn)確和PHP沒有任何關(guān)系,PHP不背這個(gè)鍋。
歡迎關(guān)注二維碼,一起交流學(xué)習(xí)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/22369.html
摘要:驗(yàn)證是否含有等字符驗(yàn)證漢字驗(yàn)證地址驗(yàn)證驗(yàn)證電話號(hào)碼正確格式為,,,,,。驗(yàn)證身份證號(hào)位或位數(shù)字驗(yàn)證一年的個(gè)月正確格式為和驗(yàn)證一個(gè)月的天正確格式為和。 Js代碼 function SubmitCk() { var reg = /^([a-zA-Z0-9]+[_|\_|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|.]?)*...
摘要:類型使用的就是標(biāo)準(zhǔn)中的雙精度浮點(diǎn)數(shù)。數(shù)字的許多特性都依賴于此標(biāo)準(zhǔn),例如令人費(fèi)解的不等于這篇文章介紹標(biāo)準(zhǔn)中雙精度浮點(diǎn)數(shù)二進(jìn)制儲(chǔ)存格式,并由此推出中數(shù)字的一些特性。 Javascript 作為一門動(dòng)態(tài)語(yǔ)言,其數(shù)字類型只有 number 一種。 nubmer 類型使用的就是 IEEE754 標(biāo)準(zhǔn)中的 雙精度浮點(diǎn)數(shù)。Javascript 數(shù)字的許多特性都依賴于此標(biāo)準(zhǔn),例如令人費(fèi)解的 0.1+0...
摘要:前端中的計(jì)算機(jī)領(lǐng)域的通常認(rèn)為起源于。并對(duì)其主要內(nèi)容作了自己的解讀。搬到另一個(gè)地區(qū)會(huì)導(dǎo)致名氣降低。年度報(bào)告,年最受歡迎的編程語(yǔ)言年上最流行的種編程語(yǔ)言及前十最火熱的項(xiàng)目排行榜,分別由及登頂。技術(shù)周刊由小組出品,匯聚一周好文章,周刊原文。 showImg(https://segmentfault.com/img/bVWHC4?w=1000&h=710); 本期推薦 反擊爬蟲,前端工程師的腦...
摘要:前言最近,朋友問(wèn)了我這樣一個(gè)問(wèn)題在中的運(yùn)算結(jié)果,為什么是這樣的雖然我告訴他說(shuō),這是由于浮點(diǎn)數(shù)精度問(wèn)題導(dǎo)致的。由于可以用階碼移動(dòng)小數(shù)點(diǎn),因此稱為浮點(diǎn)數(shù)。它的實(shí)現(xiàn)遵循標(biāo)準(zhǔn),使用位精度來(lái)表示浮點(diǎn)數(shù)。 showImg(https://segmentfault.com/img/remote/1460000018981071); 前言 最近,朋友 L 問(wèn)了我這樣一個(gè)問(wèn)題:在 chrome 中的運(yùn)算...
摘要:由于浮點(diǎn)數(shù)不是精確的值,所以涉及小數(shù)的比較和運(yùn)算要特別小心。根據(jù)標(biāo)準(zhǔn),位浮點(diǎn)數(shù)的指數(shù)部分的長(zhǎng)度是個(gè)二進(jìn)制位,意味著指數(shù)部分的最大值是的次方減。也就是說(shuō),位浮點(diǎn)數(shù)的指數(shù)部分的值最大為。 一 前言 這篇文章主要解決以下三個(gè)問(wèn)題: 問(wèn)題1:浮點(diǎn)數(shù)計(jì)算精確度的問(wèn)題 0.1 + 0.2; //0.30000000000000004 0.1 + 0.2 === 0.3; // ...
閱讀 2747·2021-11-25 09:43
閱讀 2541·2021-09-22 15:29
閱讀 1251·2021-09-22 15:17
閱讀 3723·2021-09-03 10:36
閱讀 2292·2019-08-30 13:54
閱讀 1826·2019-08-30 11:23
閱讀 1234·2019-08-29 16:58
閱讀 1347·2019-08-29 16:14