問題是這樣的~
我要用PHP做一個統計並輸出至EXCEL~
統計資料中有百分比的計算..
所有的統計程式都一樣~
輸出也都正常~
但唯獨其中一個值出現異常....
如下:
round((1/1435)*100,2)
上面這段..理論上結果應該是0.07
但是實際卻跑出0.07000000000000001
且已經故意另外嘗試其上下100的值(1535~1335)
結果是一樣的..
過了這個範圍就正常了
這問題已在聊天室發問過~
本想說沒解決也沒關係
所以才在聊天室當作聊天發問~
沒想到異常熱烈討論...= =
(有熱烈嗎?0.0)
已有神人回答~
嘗試修改php.ini內的precision值為14
但我查過已經是14~
也試過故意改別的值再phpinfo()出來
所以確定是那個php.ini檔案~
不過當我把設定的值已程式碼的方式執行在PHP中
ini_set('precision', '14');
結果成功了...
round((1/1435)*100,2)
輸出結果為0.07
賽門 大大~
不求解~ㄎㄎ~XDD
php的浮點運算的精確度有限: https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
我們看到的十進位浮點, 內部事實上是二進位浮點.
php.ini的precision內定是14, 足夠"商業"運算. 如果要求精密, 當您設定precision超過15, 就不能信任其精確度, 如以下的測試:
$ cat phpround.php
<?php
for ( $i=0 ; $i<24 ; $i++ ) {
ini_set('precision', $i);
echo "precision $i: ".round((1/1435)*100,2)."\n";
}
?>
我的環境是Ubuntu 16.04 64-bit, 分別用我自己編譯的php 5.6和php 7.0測試:
$ /path-to-my-php/php5.6/bin/php phpround.php
precision 0: 0.07
precision 1: 0.07
precision 2: 0.07
precision 3: 0.07
precision 4: 0.07
precision 5: 0.07
precision 6: 0.07
precision 7: 0.07
precision 8: 0.07
precision 9: 0.07
precision 10: 0.07
precision 11: 0.07
precision 12: 0.07
precision 13: 0.07
precision 14: 0.07
precision 15: 0.07
precision 16: 0.07000000000000001
precision 17: 0.070000000000000007
precision 18: 0.0700000000000000067
precision 19: 0.07000000000000000666
precision 20: 0.070000000000000006661
precision 21: 0.0700000000000000066613
precision 22: 0.07000000000000000666134
precision 23: 0.070000000000000006661338
$ /path-to-my-php/php7.0/bin/php phpround.php
precision 0: 0.07
precision 1: 0.07
precision 2: 0.07
precision 3: 0.07
precision 4: 0.07
precision 5: 0.07
precision 6: 0.07
precision 7: 0.07
precision 8: 0.07
precision 9: 0.07
precision 10: 0.07
precision 11: 0.07
precision 12: 0.07
precision 13: 0.07
precision 14: 0.07
precision 15: 0.07
precision 16: 0.07000000000000001
precision 17: 0.070000000000000007
precision 18: 0.0700000000000000067
precision 19: 0.07000000000000000666
precision 20: 0.070000000000000006661
precision 21: 0.0700000000000000066613
precision 22: 0.07000000000000000666134
precision 23: 0.070000000000000006661338
修改php.ini和在php腳本中使用ini_set來修改是一樣的, 我寫了一個腳本來模擬手動修改php.ini:
$ cat sedphpini.sh
#!/bin/bash
PHPINI=/path-to-my-php-conf-dir/php.ini
PHP=/path-to-my-php-dir/bin/php
for i in {1..24}
do
sed -i "s/^precision =.*/precision = $i/g" $PHPINI
$PHP phpround2.php
done
$ cat phpround2.php
<?php
$i=ini_get('precision');
echo "precision $i: ".round((1/1435)*100,2)."\n";
?>
執行結果:
$ ./sedphpini.sh
precision 1: 0.07
precision 2: 0.07
precision 3: 0.07
precision 4: 0.07
precision 5: 0.07
precision 6: 0.07
precision 7: 0.07
precision 8: 0.07
precision 9: 0.07
precision 10: 0.07
precision 11: 0.07
precision 12: 0.07
precision 13: 0.07
precision 14: 0.07
precision 15: 0.07
precision 16: 0.07000000000000001
precision 17: 0.070000000000000007
precision 18: 0.0700000000000000067
precision 19: 0.07000000000000000666
precision 20: 0.070000000000000006661
precision 21: 0.0700000000000000066613
precision 22: 0.07000000000000000666134
precision 23: 0.070000000000000006661338
precision 24: 0.0700000000000000066613381
至於您在php.ini的改變不能生效, 就要看您的php使用的是不是您所修改的php.ini, 可調出php -i的輸出結果來查看.
在php -a
測試了一下:
php > ini_set('precision', 14);
php > $n = floatval((0.7+0.1)*10);
php > echo $n;
8
php > ini_set('precision', 17);
php > echo $n;
7.9999999999999991
precision設定影響的是「顯示」出來的結果。zval內部應該單純就是用一個double在做計算,方法就是依照IEEE-754。不過浮點數計算本來就會有精度問題。所以http://php.net/manual/en/language.types.float.php 裡面有警告...
純聊天.....海綿寶要來趕人了。
還是要說, 沒圖沒真相。
請你貼完整Code及執行結果圖及Phpindo().輸出結果圖...
啊,已經有答案了。算了,看版大高興來貼吧。