編輯: 這個問題涉及兩個主題:雙到位浮動和浮動四捨五入
- 到位浮動使用雙精度浮點精度的
- 效率以下四捨五入
是我有什麼理由不應該總是使用Java double而不是float?
我問這個問題,因爲這個測試代碼使用浮動時失敗和不清楚爲什麼,因爲唯一的區別是使用float而不是double。
public class BigDecimalTest {
@Test public void testDeltaUsingDouble() { //test passes
BigDecimal left = new BigDecimal("0.99").setScale(2,BigDecimal.ROUND_DOWN);
BigDecimal right = new BigDecimal("0.979").setScale(2,BigDecimal.ROUND_DOWN);
Assert.assertEquals(left.doubleValue(), right.doubleValue(), 0.09);
Assert.assertEquals(left.doubleValue(), right.doubleValue(), 0.03);
Assert.assertNotEquals(left.doubleValue(), right.doubleValue(), 0.02);
Assert.assertNotEquals(left.doubleValue(), right.doubleValue(), 0.01);
Assert.assertNotEquals(left.doubleValue(), right.doubleValue(), 0.0);
}
@Test public void testDeltaUsingFloat() { //test fails on 'failing assert'
BigDecimal left = new BigDecimal("0.99").setScale(2,BigDecimal.ROUND_DOWN);
BigDecimal right = new BigDecimal("0.979").setScale(2,BigDecimal.ROUND_DOWN);
Assert.assertEquals(left.floatValue(), right.floatValue(), 0.09);
Assert.assertEquals(left.floatValue(), right.floatValue(), 0.03);
/* failing assert */ Assert.assertNotEquals(left.floatValue() + " - " + right.floatValue() + " = " + (left.floatValue() - right.floatValue()),left.floatValue(), right.floatValue(), 0.02);
Assert.assertNotEquals(left.floatValue(), right.floatValue(), 0.01);
Assert.assertNotEquals(left.floatValue(), right.floatValue(), 0.0);
}}
失敗消息:
java.lang.AssertionError: 0.99 - 0.97 = 0.01999998. Actual: 0.9900000095367432
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failEquals(Assert.java:185)
at org.junit.Assert.assertNotEquals(Assert.java:230)
at com.icode.common.BigDecimalTest.testDeltaUsingFloat(BigDecimalTest.java:34)
任何想法,爲什麼這個測試失敗,爲什麼我不應該只是總是使用浮動的雙重呢?當然,雙倍以外的原因比浮動更寬。有趣的是,Assert.assertNotEquals(double,double,delta)在兩種情況下都是雙重的,所以失敗測試中返回的浮動數據變得越來越寬,所以爲什麼測試失敗呢?
編輯: 可能是這樣的其他問題是相關的,不知道雖然: hex not the same
編輯: 從這個問題的答案hex not the same可以得出的結論是科學的表示IEEE 754 0.99浮法對於相同的值而言不同於雙倍。這是由於四捨五入。
因此,我們得到這樣的:
- 0.99 - 0.97 = 0.01999998 //在浮動情況下
- 0.99 - 0.97 = 0.020000000000000018 //雙的情況下
由於在最大增量上面的單元測試是0.02和0.01999998(在失敗的測試中)低於德爾塔值,這意味着數字看起來是相同的,但測試聲稱它們並沒有因此失敗。
你認同這一切嗎?
它似乎有浮動減法和舍入的特殊性:http://stackoverflow.com/questions/13263650/float-number-is-not-the-expected-number-after-subtraction – Francis