2017-07-24 55 views
2

我在我的代碼中發現了一個錯誤。基本上我是回到客戶的金額減去1美分,我發現這是由於詮釋鑄造。有人可以解釋爲什麼會這樣嗎?PHP向下規則

$x = 9.53 * 100; 

var_dump($x); // double(953) 
var_dump((int)$x); // int(952) 

此外,我發現這種情況並非發生在所有情況下。 例如:

echo (int)(9.52 * 100)//952 
echo (int)(9.53 * 100)//952 
echo (int)(9.54 * 100)//953 
echo (int)(9.55 * 100)//955 

我解決這個問題是先計算其丟字符串,並投它來詮釋,它似乎是工作

+0

爲什麼你不簡單地回聲(9.52 * 100)。或者如果你想確定你沒有得到小數,你只需做下面的回合($ calculation,0)? – DaAmidza

+1

我不知道爲什麼它像這樣工作,但爲了安全,我通常堅持'bcmath'。例如。 '$ result = bcmul(9.53,100);'(它返回字符串,但將其轉換爲浮點數不會中斷結果) – Volvox

+0

@Arslan.H要點是要確定它發生的原因。 Volvox與我解決問題的方法類似。託託顯示了它發生的原因 – dixromos98

回答

4

這是不是一個錯誤,這是因爲浮動號碼的表示。

在內存方面,9.53不準確9.53,使用printf看到:

$y = 9.53; 
printf("%.25f\n", $y); 
$x = 9.53 * 100; 
printf("%.25f\n", $x); 

輸出:

9.5299999999999993605115378 
952.9999999999998863131622784 
+0

我假設它,但你確認了我的假設。乾杯。 – dixromos98

+0

@ dixromos98:不客氣,很高興幫助。 – Toto

1

有人可以解釋爲什麼發生這種情況?

在計算機中,實數不是精確存儲的。它們是近似值。

在現實生活中,以10爲底的計算,1/30.33333....。不能準確地寫出它,無論他們在十進制數字之後放置多少個3。當且僅當n的唯一素數因子是25(基數的主要因子)時,有理數m/n具有基數10中的小數比率的有限表示形式。

在計算機中,一切都使用基地2存儲。這意味着基數10(如9.53)中的有限表示的大多數數字在基數2中沒有有限表示,而實際上它們的近似值實際上是存儲的。

乘以9.53100沒有多大幫助。由於最初的錯誤,結果大致爲953。因爲它比953小,(int)(9.53*100)產生952

你的情況已經記錄在PHP手冊頁約integers

警告

決不投未知的分數integer,這樣有時會導致意外的結果。請參閱warning about float precision

有此問題的幾種解決方案:你可以用number_format()獲得無小數位數的字符串表示,然後使用intval()獲得整數值。

另一種解決方法是對round()返回的值應用(int)類型轉換(但對於某些值可能不起作用)。

+0

感謝您的詳細解釋。目前解決此問題的方法是進行計算並將其轉換爲字符串,然後將其轉換爲整數並將其返回給函數。通過一些單向測試和日常監控,這個臨時解決方案似乎能夠解決問題。 – dixromos98