问题。我有一个双字符串“0.4 0.3 2.1等”。 我需要在这个列表中循环并计算每个数字的出现次数。
我用过
StringTokenizer stokens = new StringTokenizer(values);
while(stokens.hasMoreTokens()) {
Double tempKey = new Double(stokens.nextToken());
Integer tempCount = orderValues.get(tempKey);
if (tempCount == null)
tempCount = 1;
else
tempCount++;
orderValues.put(tempKey, tempCount);
}
其中 values 是字符串, orderValues 是TreeMap。
在此之后,我必须将从0到最大键值的所有缺失值添加到TreeMap中,并显示0。 所以我用
for(double i = 0; i<=orderValues.lastKey(); i+=0.1) {
if (orderValues.get(new Double(i))==null) {
orderValues.put(i,0);
}
}
问题是双重迭代。我需要迭代double值的第一个小数。 这是输出。
0.0 => 0
0.1 => 0
0.2 => 0
0.30000000000000004 => 0
0.4 => 0
0.5 => 1
0.6 => 1
0.7 => 0
0.7999999999999999 => 0
0.8999999999999999 => 0
0.9999999999999999 => 0
1.0999999999999999 => 0
1.2 => 2
1.3 => 0
1.4 => 2
1.4000000000000001 => 0
etc..
当然这是一个问题(看看1.4和1.4000000001)。 我该如何防止这种情况?
主要问题是迭代双倍0.1值
我如何修复(感谢Roel)。 我已将for语句改为
for(double i = 0.1; i<=orderValues.lastKey(); i=rounding(0.1+i)) {
并添加了舍入函数
private double rounding(double x) {
BigDecimal bd = new BigDecimal(x);
bd = bd.setScale(1, RoundingMode.HALF_UP);
return bd.doubleValue();
}
答案 0 :(得分:2)
你正在使用原始double和类类型Double,并且它们之间正在进行转换,因为它们都是浮点,你会看到浮点不精确。
答案 1 :(得分:2)
双重类型缺乏精确性是众所周知的。通常,解决方案是使用BigDecimal。但是在您的特定情况下,由于您在每次迭代时步进0.1,您还可以使用整数,并在需要时将它们除以10。
请注意,您还应该更改存储数据的方式。也就是说,使用:
TreeMap<BigDecimal, Integer>
(or TreeMap<Integer, Integer>) instead of TreeMap<Double, Integer>
另请参阅BigDecimal的文档:http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html 它不像双重一样容易使用,但更安全。