1

I retrieve from an XML file a float number that I want to format and insert in a text file with the pattern 8 digits after comma, and 2 before.

Here is my code:

String patternNNDotNNNNNNNN = "%11.8f";
float value = 1.70473711f;
String result = String.format(java.util.Locale.US, patternNNDotNNNNNNNN, value);
System.out.println(result);

As a result I get: 1.70473707

Same problem if I use:

java.text.DecimalFormatSymbols symbols = new java.text.DecimalFormatSymbols(java.util.Locale.US);
java.text.DecimalFormat df = new java.text.DecimalFormat("##.########", symbols);
System.out.println(df.format(value));

I don't understand why I have a rounded value (1.70473711 comes to 1.70473707).

Tom
  • 16,842
  • 17
  • 45
  • 54
  • 4
    Floats have limited precision. See what happens with a double. (of course doubles have limited precision too, but they have more than a float) – tgdavies Jul 20 '21 at 10:01
  • 3
    [How many significant digits do floats and doubles have in java?](//stackoverflow.com/q/13542944) – Tom Jul 20 '21 at 10:03
  • Related, with lots of relevant links: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – Hulk Jul 20 '21 at 10:19

2 Answers2

0

This is because the precision of the float means that the value 1.7043711 is not actually 1.7043711.

Consider the following which process 1.70473711f as both a float and a double:

String patternNNDotNNNNNNNN = "%11.8f";

float valueF = 1.70473711f;
String result = String.format(java.util.Locale.US, patternNNDotNNNNNNNN, valueF);
System.out.println(valueF);
System.out.println(result);

double valueD = 1.70473711f;
result = String.format(java.util.Locale.US, patternNNDotNNNNNNNN, valueD);
System.out.println(valueD);
System.out.println(result);

Output:

1.7047371
 1.70473707
1.7047370672225952
 1.70473707

When treating the value as a double, you can see that 1.7043711f is actually 1.7047370672225952. Rounding that to 8 places gives 1.70473707 and not 1.70473711 as expected.

Instead, treat the number as a double (i.e. remove the f) and the increase precision will result in the expected output:

double valueD = 1.70473711;
String result = String.format(java.util.Locale.US, patternNNDotNNNNNNNN, valueD);
System.out.println(valueD);
System.out.println(result);

Output:

1.70473711
 1.70473711
Martin
  • 16,093
  • 1
  • 29
  • 48
-1

String.format on floating point values does round them. If you don't want that, use BigDecimal. See

double d = 0.125;
System.out.printf("%.2f%n", d);
g00se
  • 3,207
  • 2
  • 5
  • 9