php中浮點數的精度值是用來控制輸出該浮點數時使用的,可以理解為控制輸出的位數,精度值不同,看到輸出結果也可能不一樣,注意:其內部還是按照實際值存儲的,當兩個浮點數進行四則運算時,用的還是其本來的值。
php的配置文件中使用precision來設定全局指定浮點數的精度值,似乎每個發行版,它的默認設置都不太一樣,我在window下看到是12,在linux下看到此值是14,當然也可以通過程序中使用ini_set來改變全局設置,例如:
代碼如下 復制代碼 ini_set("precision", "15");對於精度我一直理解為小數點後保留多少,那麼在php的浮點數中是這樣的麼?答案是否定的。
浮點數其實是整數部分和小數部分組成,這裡的精度是指整數部分的位數加小數部分的位數不能超過其精度最大值,如果超過,則按照四捨五入的方法截斷到最大的精度值。整數部分如果是0,則不計位數,小數部分末尾0也不計入位數。另外對於同一個數,precision的不同,可能顯示的出來表現形式也不一樣。下面通過例子的方式來說明。
整數部分為 0 情況
代碼如下 復制代碼
$num = 0.12345600000000000;
//整數部分為0 ,位數為 0 ,小數部分末尾的 0 不計入位數,所以總位數為 6
ini_set("precision", "12");
echo $num; // 0.123456
//未超過精度值,顯示的結果為 0.123456
ini_set("precision", "3");
echo $num; // 0.123
//超過精度值,保留3位
ini_set("precision", "5");
echo $num; // 0.12346
//超過精度值,保留5位這種情況下,精度值等價於小數點後保留幾位。
整數部分大於 0 情況
代碼如下 復制代碼 $num = 12.12345600000000000;
//整數部分為12 ,位數為 2 ,小數部分末尾的 0 不計入位數,位數為6,所以總位數為 2 + 6
ini_set("precision", "12");
echo $num; // 12.123456
//未超過精度值,顯示的結果為 12.123456
ini_set("precision", "3");
echo $num; // 12.1
//超過精度值,整數部分位數為 2 ,所以只保留一位小數
ini_set("precision", "5");
echo $num; // 12.123
//超過精度值,整數部分位數為 2 ,所以只保留3位小數可以看到小數點後保留的位數跟精度已經整數部分的位數有關
。
整數部分大於 0 情況 之二
代碼如下 復制代碼 $num = 12345678.12345600000000000;
//整數部分為12345678 ,位數為 8 ,小數部分末尾的 0 不計入位數,位數為6,所以總位數為 8 + 6
ini_set("precision", "12");
echo $num; // 12345678.1235
//超過精度值,顯示的結果為 12345678.1235
ini_set("precision", "3");
echo $num; // 1.23E+7
//超過精度值,且整數部分位數超過精度,小數部分捨棄,且整數部分只取3位
ini_set("precision", "5");
echo $num; // 12346000
//超過精度值,且整數部分位數超過精度,小數部分捨棄,且整數部分只取5位上述例子中可以看到,精度值也關系到整數部分的截取。注意到最後兩個例子中顯示的方式不一樣,一個是使用科學計數法,一個是後面用 0 補。通過實驗得出的結論是當整數部分的位數 減去 精度值 大於 4 的時候,使用科學計數法的方式,否則後面用 0 補,換句話說,就是整數部分位數超過精度值後,截斷後,補 0 的個數不會超過 4 。
浮點數運算
代碼如下 復制代碼 $num1 = 1331625729.687;
$num2 = 1331625730.934;
ini_set("precision", "8");
echo $num1 . '
';
echo $num2 . '
';
$sub = $num1 - $num2;
echo $sub . '
';
//輸出的結果為:
/*
1331625700
1331625700
-1.247
*/
上述例子就說明了精度值只是控制顯示結果,內部存儲還是原始值,所以 $sub 的值為1331625729.687減1331625730.934。
PHP內置的echo, var_dump, json_encode, 字符串拼接等函數(指令)在顯示浮點數時都有問題, 導致精度丟失.
代碼如下 復制代碼<?php
$a = 1315537636.338467;
printf("%f", $a); echo "n";
echo $a . "n";
echo $a; echo "n";
?>
結果
1315537636.338467
1315537636.3385
1315537636.3385
也就是說, 用PHP最順手的方法將浮點數轉成字符串或者顯示是不行的, 必須使用printf/sprintf將浮點數轉成字符串.