I need to extract the decimal part of a float number, but I get weird results:
float n = 22.65f; // I want x = 0.65f, but... x = n % 1; // x = 0.6499996 x = n - Math.floor(n); // x = 0.6499996185302734 x = n - (int)n; // x = 0.6499996
Why does this happen? Why do I get those values instead of 0.65
?
Advertisement
Answer
float
only has a few digit of precision so you should expect to see a round error fairly easily. try double
this has more accuracy but still has rounding errors. You have to round any answer you get to have a sane output.
If this is not desireable you can use BigDecimal which does not have rounding errors, but has its own headaches IMHO.
EDIT: You may find this interesting. The default Float.toString() uses minimal rounding, but often its not enough.
System.out.println("With no rounding"); float n = 22.65f; System.out.println("n= "+new BigDecimal(n)); float expected = 0.65f; System.out.println("expected= "+new BigDecimal(expected)); System.out.println("n % 1= "+new BigDecimal(n % 1)); System.out.println("n - Math.floor(n) = "+new BigDecimal(n - Math.floor(n))); System.out.println("n - (int)n= "+new BigDecimal(n - (int)n)); System.out.println("With rounding"); System.out.printf("n %% 1= %.2f%n", n % 1); System.out.printf("n - Math.floor(n) = %.2f%n", n - Math.floor(n)); System.out.printf("n - (int)n= %.2f%n", n - (int)n);
Prints
With no rounding n= 22.6499996185302734375 expected= 0.64999997615814208984375 n % 1= 0.6499996185302734375 n - Math.floor(n) = 0.6499996185302734375 n - (int)n= 0.6499996185302734375 With rounding n % 1= 0.65 n - Math.floor(n) = 0.65 n - (int)n= 0.65