floating point is a binary format and it can represent numbers as a sum of powers of 2. e.g. 3.5 is 2 + 1 + 1/2.
float 3.2f as an approximation of 3.2 is
2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/4194304 + a small error
However double 3.2d as an approximation of 3.2 is
2 + 1 + 1/8+ 1/16+ 1/128+ 1/256+ 1/2048+ 1/4096+ 1/32768+ 1/65536+ 1/524288+ 1/1048576+ 1/8388608+ 1/16777216+ 1/134217728+ 1/268435456+ 1/2147483648+ 1/4294967296+ 1/34359738368+ 1/68719476736+ 1/549755813888+ 1/1099511627776+ 1/8796093022208+ 1/17592186044416+ 1/140737488355328+ 1/281474976710656+ 1/1125899906842624 + a smaller error
When you use floating point, you need to use appropriate rounding. If you use BigDecimal instead (and many people do) it has rounding built in.
double dd = 3.2;
float ff = 3.2f;
// compare the difference with the accuracy of float.
System.out.println(Math.abs(dd - ff) < 1e-7 * Math.abs(ff));
BTW the code I used to print the fractions for double.
double f = 3.2d;
double f2 = f - 3;
System.out.print("2+ 1");
for (long i = 2; i < 1L << 54; i <<= 1) {
f2 *= 2;
if (f2 >= 1) {
System.out.print("+ 1/" + i);
f2 -= 1;
}
}
System.out.println();