问题
I understand that computer can not represent non-integral numbers precisely. so when I add 2 doubles in java for example:
724.64d + 1000d
the console print out 1724.6399999999999
but why for 724.64d + 100d and 724.64d + 10000d
the console print out 824.64 and 10724.64 separately?
is there a way to know at what condition when I add the 2 doubles, the sum is the exact number ?
The reason why I ask is because that our old program use double to do calculation. and use double comparison to validate the numbers.
for example: let us say the total is 1849.64, all the inputs amounts added up must be equals to total which is 1849.64
input 1: 724.64
input 2: 1125
will not work, because the sum will be 1849.6399999999999
but if we input like this below will work, and the sum is 1849.64
input 1: 24.64
input 2: 1825
so how to find those combinations that work? Note, I do not have access to this specific very old program. when the validation failed, we have to manually find a walk around like the second inputs combination. Thanks.
回答1:
BigDecimal bigDecimal = new BigDecimal(724.64);
bigDecimal = bigDecimal.add(new BigDecimal(1000.0));
System.out.println(bigDecimal.floatValue());<--Works fine
System.out.println(bigDecimal.doubleValue());<--Works as mentioned in Question
Output:
1724.64
1724.6399999999999
In the first case it works because of narrowing primitive conversion happens. But with Floating-Point numbers you will have to accept and live with it.
As I stated the reason it is valid for primitives
double d = 724.64;
double d1 = 1000.0;
System.out.println(d + d1);
System.out.println((float) (d + d1));
Output:
1724.64
1724.6399999999999
回答2:
Floating-point numbers don't represent numbers in the decimal, but in binary system and obviously they are of only finite precision, so there is a mismatch between the exact values a decimal system represents and those a floating-point number can represent. You must not expect it to do so.
回答3:
Rather than try to determine what conditions result in exact or inexact calculations consider using BigDecimal for these situations.
回答4:
To answer your final question, a double is exact if the fractional part is a negative power of two, for example zero, 1/2, 1/4, 1/16, ..., It will appear to be exact in some other cases, like the ones you posted, if the API you use to convert them to decimal (for example System.out.println()) does rounding or truncation and the value is close enough that the rounding or truncation yields the expected answer.
回答5:
If comparison is the issue, as a workaround, I would advice to format the numbers in string with 2 decimal places and rounding done and then compare the strings:
double expectNum = 1849.64;
double resultNum = 1849.639999;
String expectedString = String.format("%.2g%n", expectNum);
String resultString = String.format("%.2g%n", resultNum);
if(expectedString.equals(resultString)){
//result matched
//return true;
}else{
//return false;
}
来源:https://stackoverflow.com/questions/13093982/java-double-calculation