在Java

时间:2015-06-24 09:10:55

标签: java for-loop double treemap double-precision

问题。我有一个双字符串“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();
}

2 个答案:

答案 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 它不像双重一样容易使用,但更安全。