Super_Hippo wrote ...

2018/1/11

# Sum of array

Super_Hippo

2018/1/11

Just a short question here: Why does this code
import greenfoot.*;

public class MyWorld extends World
{
public MyWorld()
{
super(600, 400, 1);
double[] x = {0.4, 0.3, 0.2, 0.1};
double sum = 0;
for (double d : x)
{
sum += d;
System.out.println(sum);
}
}
}
print out this
0.4
0.7
0.8999999999999999
0.9999999999999999
and not
0.4
0.7
0.9
1.0
?
danpost

2018/1/11

Computers store values in base 2 (either a bit is on or it is off). It cannot store exactly any non-integer value that is not the sum of a finite number of powers of 2 or whose any two powers of 2 in its binary representation are far removed from each other. Take a simple number like 0.4 and try to convert it to binary -- you get 0.011010.. -- with the fractional digits repeating; therein being some loss in precision. These tiny losses add up, giving what you have discovered. If your precision is to be to one decimal place, you could store the number as integers where one represents 1/10 of a unit:
int[] x = { 4, 3, 2, 1 };
int sum = 0;
for (int i : x)
{
sum += i;
System.out.println((double)sum/10.0);
}
Super_Hippo

2018/1/12

I never thought about this. I thought decimal numbers would be stored as a "string" of digits and that having one single decimal place couldn't lose any precision. But that makes sense, thank you!
danpost

2018/1/12

Actually, the binary equivalent to 0.4 above was incorrect; but, my point still holds. The correct binary value should be 0.0110... with the fractional part repeating.