2011-06-28 100 views
0

我已經有了一個奇怪的PHP行爲與浮點值問題浮點值

$array_test["test"]= round($value,2); //first I round up a value 
echo $array_test["test"]; //0,66 
$s_array_test= serialize($array_test); //serializing the array 
var_dump($s_array_test) // (...)s:4:"test";d:0.66000000000000003108624468950438313186168670654296875;}(...) 

這是非常惱人的原因序列化數組存儲到數據庫中一個使用更多的空間......

如何解決這個問題 ?

THX

+0

爲什麼不將值存儲在數據庫中,而不是複雜的結構? (順便說一句:你「鬆」只有32byte。如果你問我,它並不是那麼多)而且你似乎沒有提供你使用的真實代碼。你使用一個無效值_overwrite_'test''的值,_after_'round()'有一個無效值(應該是'0.66') – KingCrunch

+0

如果我直接在db中存儲值,這會使我有很多字段可以有點煩人的代碼,我只是在uniq calcul中使用所有的值,所以...我只是修復代碼thx – krifur

+0

另請參閱:http://stackoverflow.com/questions/6503928/a-php-bug-非常簡單的如何修復 – kapa

回答

3

首先閱讀有關漂浮在部分手動http://php.net/manual/en/language.types.float.php

浮點數具有有限的精度。雖然它取決於系統,但PHP通常使用IEEE 754雙精度格式,由於四捨五入的順序爲1.11e-16,因此會產生最大相對誤差。非基本的算術運算可能會導致更大的錯誤,當然,當多個運算複合時,必須考慮錯誤編程。

此外,基數10中的浮點數(如0.1或0.7)可以精確表示的有理數作爲基數2中的浮點數沒有精確的表示,在內部使用該浮點數,無論大小尾數。因此,他們不能被轉換成其內部的二進制對應,而不會有小的精度損失。這可能導致令人困惑的結果:例如,floor((0.1 + 0.7)* 10)通常會返回7而不是預期的8,因爲內部表示將類似於7.9999999999999991118 ....

因此永遠不要相信浮點數結果到最後一位,並且從不比較浮點數是否相等。如果需要更高的精度,則可以使用任意的精度數學函數和gmp函數。

您可以使用(而不是round()sprintf()到浮動轉換成固定大小的字符串

sprintf('%.2f', $float); 

但我建議你創建和使用一個真正的數據庫架構。如果你只是把非結構化的字符串放在裏面,你根本不需要數據庫。您可以改爲使用簡單的平面文件。

+0

sprintf的+1。比我的字符串鑄造好得多;) – Yoshi

+0

它仍然不起作用,如果我用sprintf替換圓形指令,則在序列化數組之後出現一堆數字... – krifur

+0

「一堆數字」?也許你還有其他問題?只是再次測試它,並在這裏工作正常'$ float = 0.66342534675; var_dump(sprintf('%2f',$ float)); 字符串(4)「0.66」' – KingCrunch

1

它可能表現如此,因爲表中的數據類型是varchar或任何非數字數據類型。 我不認爲這是唯一的原因,但它可以成爲其中的一個。

+0

數據類型爲Text導致它可能相當大並且包含字母數字字符 – krifur