简体   繁体   中英

For-loop with double in Java

Problem. I have a String of double "0.4 0.3 2.1 etc". I need to loop in this list and count occurencies of each number.

I used

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);
}

where values is the string and orderValues is a TreeMap.

After this I have to add to the TreeMap all missing values from 0 to max key Value with a 0 occurency. So I use

for(double i = 0; i<=orderValues.lastKey(); i+=0.1) {
    if (orderValues.get(new Double(i))==null) {
        orderValues.put(i,0);
    }
}

The problem is the iteration on the double. I need to iterate just on the first decimal of double value. This is the output.

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..

And of course it's a problem (look at 1.4 and 1.4000000001). How can I prevent this?

The main problem is iterate on double by 0.1 value


How I Fixed (thanks to Roel). I've changed the for statement into

for(double i = 0.1; i<=orderValues.lastKey(); i=rounding(0.1+i)) {

and added the rounding function

private double rounding(double x) {
    BigDecimal bd = new BigDecimal(x);
    bd = bd.setScale(1, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

您正在使用原始的double和类类型Double,并且它们之间正在进行转换,并且由于它们都是浮点,因此您会看到浮点不精确。

The lack of precision of double types is well-known. Usually, a solution is to use BigDecimal instead. However in your specific case, since you're stepping 0.1 at each iteration, you could also work with integers, and divide them by 10 when needed.

Note that you should also change the way you store the data. That is, use:

TreeMap<BigDecimal, Integer>

(or TreeMap<Integer, Integer>) instead of TreeMap<Double, Integer>

See also the documentation of BigDecimal: http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html It's not as easy to use as double, but much safer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM