php中小數精度的代碼解析

來源:互聯網
上載者:User
本篇文章給大家帶來的內容是關於php中小數精度的代碼解析,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所協助。

項目中保留兩位小數四捨五入遇到精度問題:

$num = 0.99;$num1 = round($num, 2);//0.98999999999999999$num2 = floatval($num);//0.98999999999999999

目前解決方案:

sprintf("%.2f", round($money, 2));//會自動四捨五入echo substr(sprintf("%.3f",$n), 0, -1);//不四捨五入

測試結果:

var_dump(json_encode(round(0.99 ,2)));//0.98999999999999999var_dump(round(0.99 ,2));//0.99$f = 0.58;    var_dump(intval($f * 100));//57

關於等於57這個問題,我們可以分析一下:

浮點數的表示(IEEE 754:IEEE二進位浮點數算術標準):

  浮點數, 以64位的長度(雙精確度)為例, 會採用1位符號位(E), 11指數位(Q), 52位尾數(M)表示(一共64位).

  符號位:最高位表示資料的正負,0表示正數,1表示負數。

  指數位:表示資料以2為底的冪,指數採用位移碼錶示

  尾數:表示資料小數點後的有效數字.

0.58 對於二進位表示來說, 是無限長的值:

  0.58的二進位表示基本上(52位)是: 0010100011110101110000101000111101011100001010001111

0.57的二進位表示基本上(52位)是: 001000111101011100001010001111010111000010100011110

而兩者的二進位, 如果只是通過這52位計算的話,分別是:

   0.58 --> 0.57999999999999996

0.57 --> 0.5699999999999999

所以,0.58 * 100 結果會:57.999999999,轉成整型:57

關於浮點數的二進位表示可以參考:浮點數的二進位表示

類似:

(0.1 + 0.7) == 0.8//falsefloor((0.1+0.7)*10)//7 //內部結果可能是:7.9999999999//所以:不可能精確的用有限位元表達某些十進位分數1/3=3.33333333333//而3.333333333333333*3,卻不是1

所以結論:

所以永遠不要相信浮點數結果精確到了最後一位,也永遠不要比較兩個浮點數是否相等。如果確實需要更高的精度,應該使用任意精度數學函數或者 gmp 函數

建議使用高精度函數:

高精度函數

  • bcadd — 2個任意精度數位加法計算

  • bccomp — 比較兩個任意精度的數字

  • bcp — 2個任意精度的數字除法計算

  • bcmod — 對一個任意精度數字模數

  • bcmul — 2個任意精度數字乘法計算

  • bcpow — 任意精度數位乘方

  • bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus

  • bcscale — 設定所有bc數學函數的預設小數點保留位元

  • bcsqrt — 任意精度數位二次方根

  • bcsub — 2個任意精度數位減法

使用高精度函數實現四捨五入:

    function getBcRound($number, $precision = 0)    {        $precision = ($precision < 0)                   ? 0                   : (int) $precision;        if (strcmp(bcadd($number, '0', $precision), bcadd($number, '0', $precision+1)) == 0) {            return bcadd($number, '0', $precision);        }        if (getBcPresion($number) - $precision > 1) {            $number = getBcRound($number, $precision + 1);        }        $t = '0.' . str_repeat('0', $precision) . '5';        return $number < 0               ? bcsub($number, $t, $precision)               : bcadd($number, $t, $precision);    }        function getBcPresion($number) {        $dotPosition = strpos($number, '.');        if ($dotPosition === false) {            return 0;        }        return strlen($number) - strpos($number, '.') - 1;    }        $money = getBcRound(0.99, 2);

相關文章推薦:

PHP中AES加密檔案的解析(附代碼)

php的curl中post方式和get方式的請求代碼

關於PHP中間鍵的內容解析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.