question

christian.n avatar image
1 Like"
christian.n asked Ben Wilson commented

Possible bug in adding double precision numbers

Hi all.

I have come across an interesting phenomenon.

I had a function in a model, which summed up values in a table and alerted me if the sum differed from 1.

When I filled in 20 rows of 0.05, I got an alert.

(The same is true for 10 rows of 0.1, but not two rows of 0.5 or 4 rows of 0.25)

I couldn't understand why this happened, so I did a test.

double value = 0;
for(int x=1;x<=20;x++) {
	value+=0.05;
}
return value;
/*Returns 1*/

This returns 1 as expected, but if I try to compare the result to 1, it returns a false/0 as seen below.

double value = 0;
for(int x=1;x<=20;x++) {
	value+=0.05;
}
return value==1;
/*Returns 0*/

Finally, I tried adding 0.05 together 20 times without the for loop, and FlexSim still returns a 0.

double value = 0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05;
return value==1;
/*returns 0, although the value is 1*/

double value = 0.5+0.5;
return value==1;
/*Returns 1*/

Have I had way too much coffee today, or is something here not working as intended? :-)

Can anyone else recreate this issue? (I got the same results on two different machines - I also tried in the 2018 beta and FlexSim HC 5.1 with the same result)

Best regards
Christian

FlexSim 17.2.3
bug report
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

1 Answer

Cameron Pluim avatar image
5 Likes"
Cameron Pluim answered Ben Wilson commented

@christian.norregaard

There is always a possibility of rounding errors when comparing doubles. Here's a link to some discussion about it on stack overflow.

As for within FlexSim, you can see that the difference between "value" and "1" is between 2E-16 and 3E-16.

double value = 0;
for(int x=1;x<=20;x++) {
	value+=0.05;
}
return (Math.fabs(value - 1)) < .0000000000000002;
/*Returns 0*/
return (Math.fabs(value - 1)) < .0000000000000003;
/*Returns 1*/

So taking example from the stack overflow page, it might be best to set a macro to be 3E-16, and use the following:

return (Math.fabs(value - 1)) < EPSILON_MACRO; //EPSILON_MACRO = 3E-16

Or, if you are not in need of that much precision, you can set the macro to be 1E-15 or something within your parameters for precision.

· 1
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.