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