2014-02-18 102 views
0

我想知道爲什麼我的浮動不圓。 當我做到這一點:圓浮動不起作用

$shipping_cost = float(57.599999999999994) 
round($shipping_cost, 2) 

結果是:57.600000000000001

你有任何想法,爲什麼會這樣? 它與服務器有關嗎?

謝謝

+1

TL; DR:浮點數學設計有缺陷。在你的情況下,你應該使用'sprintf('%2f',$ cost)',因爲它會給你一個數字的_string_表示。 – raina77ow

+0

最接近57.599999999999994的雙精度數字正好是'57.599999999999994315658113919198513031005859375'。函數'round()'被賦予了一個不可能的任務,即創建一個接近點後兩位數的雙精度的雙精度。這個雙精度數不存在,函數'round()'不應該存在,因爲它不可能完成它的工作。它決定返回'57.60000000000000142108547152020037174224853515625'',這是57.6的兩倍。 –

+0

@ raina77ow:鑑於浮點運算有缺陷,你會改變什麼,具體來說,你會改變什麼? –

回答

1

雖然您沒有指定使用什麼語言或實現,但幾乎可以肯定使用IEEE-754 64位二進制浮點格式。

在這種格式中,有限數˚F表示爲整數從-2 到2 (不包括)和兩個-1074升高到一些功率Ë範圍到971(包括的)。每個有限浮點值的格式爲f•2 e。 (這些部分在編碼存儲時略有改動,但這種描述在數學上是等同的。)

要表示一個數字,就必須把它放到這個表格中。例如,.75是3•2 -2

在這種形式下,值57.6不能寫成,正好是。最接近的可能值是8106479329266893•2 -47 = 8106479329266893/140737488355328 = 57.60000000000000142108547152020037174224853515625。 (你無法接近57.6,因爲給分子增加+1或-1會使得離57.6更遠的值移動,並且指數增加1會使分子超過2 。所以這是你可以得到的最接近的值浮點格式的邊界)。

這就是round(57.599999999999994, 2)返回的結果。

打印時,您使用的軟件會省略某些數字。它似乎打印了足夠多的數字來唯一地區分確切的值(知道浮點格式的人可以使用顯示的數字來計算確切的值),但不足以完全顯示確切的值。

1

這是最語言代表浮點值的方式發生所致。