2013-08-19 23 views
0

我有奇怪的十進制計算,真的讓我感到驚訝,我有兩個大的小數,一個是正常的程序,另一個是要約價格。然後,我想計算折扣百分比並將其上限爲最接近的整數。在Java中奇怪的十進制計算,可能是一個錯誤?

這裏是代碼:

BigDecimal listPrice = new BigDecimal(510000); 
BigDecimal offerPrice = new BigDecimal(433500); 
int itemDiscount = (int)Math.ceil(((listPrice.longValue() - offerPrice.longValue())/(float) listPrice.longValue()) * 100); 

我期望它設置爲15的itemDiscount價值,但意外的是有16個,哇。然後,我打印每個計算以表示語句的問題,所以我把的System.out.println每條語句如下:

System.out.println(listPrice.longValue() - offerPrice.longValue()); //==> show 76500 
System.out.println((listPrice.longValue() - offerPrice.longValue())/(float) listPrice.longValue()); // ==> 0.15 
System.out.println((listPrice.longValue() - offerPrice.longValue()) * 100/(float) listPrice.longValue()); // ==> 15.000001 

問題是在上面的語句,返回15.0 istead,它返回15.000001 。當我ceil它,它當然會返回16而不是15.

如果這種情況是什麼解釋?這是它的方式還是它是一個錯誤?

+1

啊,浮點算術的美。 –

+0

IEEE-754反擊。 –

+1

@EdwinDalorzo - 這不是IEE-754的錯。每個有限的浮點表示都會在某個點出現舍入誤差的問題。 –

回答

2

是什麼,如果這種情況下,如何解釋呢?這是它的方式還是它是一個錯誤?

它是這樣的。這不是一個錯誤。

您正在使用浮點類型(float)進行計算,並且浮點運算不準確。

我不確定這裏最好的修補程序是什麼。也許使用BigDecimal算術方法進行計算會給出更好的結果,但這絕不能保證您在這個計算中不會得到類似的問題,並且具有不同的輸入...

但是,我懷疑真正的問題在這個計算中你不應該使用ceil。即使BigDecimal會給你四捨五入的錯誤,例如如果你的計算除以3,則中間結果不能用基10表示精確表示。

使用實數進行計算的正確方法是在計算中適當考慮誤差線。