#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Adding 0.1 with double and float is not accurate

Hi. I wanted a "for" loop from 0 to 1 incrementing by 0.1. Sample code is shown below but the maths is so inaccurate it doesn't reach 1.0. This appears to be a fundamental defect. I can repeat this in Processing-3.02, Processing-2.2.1 and with different Java versions. I get the same result on my Windows laptop and on my iMac.

There is also some inaccuracy when I repeat this test in pure Java (1.7.0_79) using Eclipse (Mars) but it is not quite as inaccurate.

In either case I would expect to add 0.1 with better accuracy.

Processing code:

``````import processing.opengl.*;

void setup() {

size( 480, 360);
print("double ");
for (double d=0; d<=1.0 ; d+=0.1) {
print(" ",d);
}
println();
print("float ");
for (float f=0; f<=1.0 ; f+=0.1) {
print(" ",f);
}
println();
print("i/10.0 ");
for (int i=0; i<=10 ; i++) {
double d2 = i/10.0;
print(" ", d2);
}
println();
print("i/(float)10.0 ");
for (int i=0; i<=10 ; i++) {
float f2 = i/(float)10.0;
print(" ", f2);
}

}
``````

Processing Results:

``````double   0.0  0.10000000149011612  0.20000000298023224  0.30000000447034836  0.4000000059604645  0.5000000074505806  0.6000000089406967  0.7000000104308128  0.800000011920929  0.9000000134110451
float   0.0  0.1  0.2  0.3  0.4  0.5  0.6  0.70000005  0.8000001  0.9000001
i/10.0   0.0  0.10000000149011612  0.20000000298023224  0.30000001192092896  0.4000000059604645  0.5  0.6000000238418579  0.699999988079071  0.800000011920929  0.8999999761581421  1.0
i/(float)10.0   0.0  0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1.0
``````

Java Code:

``````public class LoopTest {

public static void main(String[] args) {
System.out.print("double ");
for (double d=0; d<=1.0 ; d+=0.1) {
System.out.print(" "+d);
}
System.out.println();
System.out.print("float ");
for (float f=0; f<=1.0 ; f+=0.1) {
System.out.print(" "+f);
}
System.out.println();

System.out.print("i/10.0 ");
for (int i=0; i<=10 ; i++) {
double d2 = i/10.0;
System.out.print(" "+d2);
}
System.out.println();

System.out.print("i/(float)10.0 ");
for (int i=0; i<=10 ; i++) {
float f2 = i/ (float)10.0;
System.out.print(" "+f2);
}
System.out.println();

}

}
``````

Java Results;

``````double  0.0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999
float  0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.70000005 0.8000001 0.9000001
i/10.0  0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
i/(float)10.0  0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
``````

Any thoughts as to why such a simple calculation is so inaccurate?

:-S

Tagged:

• edited May 2016 Answer ✓
• edited May 2016 Answer ✓

``````println("double: ");
for (double d = 0d; d <= 1d; d += .1d)  print(d, TAB);

println("\n\nfloat: ");
for (float f = 0.0; f <= 1.0; f += .1)  print(f, TAB);

println("\n\ni/10d: ");
for (int i = 0; i <= 10; ++i) {
double d = i/10d;
print(d, TAB);
}

println("\n\ni/10f: ");
for (int i = 0; i <= 10; ++i) {
float f = i/10.0;
print(f, TAB);
}

exit();
``````

``````double:
0.0     0.1     0.2     0.30000000000000004     0.4     0.5     0.6     0.7
0.7999999999999999  0.8999999999999999  0.9999999999999999

float:
0.0     0.1     0.2     0.3     0.4     0.5     0.6     0.70000005
0.8000001   0.9000001

i/10d:
0.0     0.1     0.2     0.3     0.4     0.5     0.6     0.7     0.8     0.9     1.0

i/10f:
0.0     0.1     0.2     0.3     0.4     0.5     0.6     0.7     0.8     0.9     1.0
``````

• Any thoughts as to why such a simple calculation is so inaccurate?

The accuracy is better than 0.0001% which is very, very good.

Java like many languages uses 4 bytes to store a float that 32 bits which gives just 4,294,967,296 different combinations to store an infinite number of floating point so some innacuracy is to be expected.

• edited May 2016 Answer ✓

The float n.000000000r occurs because of rounding errors in the the mantissa IIRC. A floating point number is written by the machine as a scientific number like 123*10^7. Rounding errors make those weird artifacts with floats.

To not have errors, use BigDecimal.

``````    /*  EXAMPLE: Using BigDecimals.
// BigDecimal is used for accurate arithmetic of any real number.
// BigDecimal is intended to work with databases and very long numbers.
// It can calculate a floating point number with desired precision, without errors.
// If your project requires exact numbers and is not real-time oriented, then BigDecimal is appropriate.
*/

import java.math.BigDecimal;

void setup() {
float a = 2;
float b = 32;

// Demonstration of wrapper functions.
float multiply = m(a, b);  // x = 2 * 32.
float division = d(a, b);  // x = 2 / 32.
float addition = a(a, b);  // x = 2 + 32.
float subtract = s(a, b);  // x = 2 - 32.

// Some weird number showing improper function use.
float improper = m(s(d(a,b),a(m(b,a),a)),s(b,a));

// Equally confusing, but still the same number as above.
float why = ((a/b)-((a*b)+a))*(b-a);

// Accuratly calculate the inverse of this massive number to the 54th decimal place.
String x = "189327469745023743269873248976983274538.745895634294783274486662066354334679694";
x = div("1.0", x, 54);

// Floating Point Rounding Error Demonstration.
double i = 189327469745023743269873248976983274538.745895634294783274486662066354334679694;
i = 1.0 / i; // Should be same operation as above, but instead finds a slightly different number faster.

println(multiply);
println(division);
println(subtract);
println(improper);
println(why);
println(x);        // 5.281853|718040743E-39     Note that x != i.
println(i);        // 5.281853|688555732E-39     Pipe inserted to highlight accuracy.
exit();
}

// Multiply Wrapper Function so we don't get carpal tunnel syndrome writing these for every operation.
float m(float a, float b) {
BigDecimal BigDec = new BigDecimal(str(a));  // Always convert value to string when calling BigDecimal.
BigDec = BigDec.multiply(new BigDecimal(str(b)));
return BigDec.floatValue();
}

// Standard Divide. Floats round their numbers after 6 places so 8 decimal places is enough for most conditions.
float d(float a, float b) {
BigDecimal BigDec = new BigDecimal(str(a)); // numerator.divide(denominator, nthDecimalPlace, roundingStyle);
BigDec = BigDec.divide(new BigDecimal(str(b)), 8, BigDecimal.ROUND_HALF_UP);
return BigDec.floatValue();
}

// String Divide
String div(String a, String b, int decimalPlace) {
BigDecimal BigDec = new BigDecimal(a); // numerator.divide(denominator, nthDecimalPlace, roundingStyle);
BigDec = BigDec.divide(new BigDecimal(b), decimalPlace, BigDecimal.ROUND_HALF_UP);
return BigDec.toString();
}

float a(float a, float b) {
BigDecimal BigDec = new BigDecimal(str(a));
return BigDec.floatValue();
}

// Subtraction
float s(float a, float b) {
BigDecimal BigDec = new BigDecimal(str(a));
BigDec = BigDec.subtract(new BigDecimal(str(b)));
return BigDec.floatValue();
}
``````
• edited May 2016 Answer ✓

Using BD for loops:

``````      for(float f=0.0; f<1.0; f=a(f, 0.1)) println(f);
``````
If I use `d += 0.1d` the Processing result is then the same as Java.