我知道计算机不能精确地表示非整数。所以当我在java中添加2个双打时,例如:
724.64d + 1000d
控制台打印出1724.6399999999999
但724.64d + 100d
和724.64d + 10000d
控制台分别打印824.64和10724.64?
有没有办法知道在我添加2个双打的情况下,总和是确切的数字?
我问的原因是因为我们的旧程序使用double来进行计算。并使用双重比较来验证数字。
例如:我们说总数为1849.64
,所有输入的金额必须等于总数1849.64
input 1: 724.64
input 2: 1125
不起作用,因为总和将是1849.6399999999999
但如果我们这样输入下面的话会有效,总和是1849.64
input 1: 24.64
input 2: 1825
那么如何找到有效的组合呢? 注意,我无法访问这个特定的非常旧的程序。当验证失败时,我们必须手动找到像第二个输入组合一样的走动。 感谢。
答案 0 :(得分:2)
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
输出:
1724.64
1724.6399999999999
在第一种情况下,由于narrowing primitive conversion
发生,它起作用。但是对于浮点数,您将不得不接受并使用它。
正如我所说,它对原语有效
double d = 724.64;
double d1 = 1000.0;
System.out.println(d + d1);
System.out.println((float) (d + d1));
输出:
1724.64
1724.6399999999999
答案 1 :(得分:1)
浮点数不代表十进制数字,但在二进制系统中显然只有有限精度,因此十进制表示的精确值与浮点数之间存在不匹配代表。你不能指望它这样做。
答案 2 :(得分:1)
考虑在这些情况下使用BigDecimal,而不是尝试确定导致精确或不精确计算的条件。
答案 3 :(得分:1)
要回答你的最后一个问题,如果小数部分是2的负幂,则双精度是精确的,例如0,1 / 2,1 / 4,1 / 16 ......,它将出现在某些其他情况下(如您发布的那些),如果用于将它们转换为十进制的API(例如System.out.println())进行舍入或截断,并且值足够接近舍入或截断产生预期的答案。
答案 4 :(得分:0)
如果比较是问题,作为解决方法,我建议格式化字符串中的数字2位小数并完成舍入,然后比较字符串:
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;
}