2

Why are the values of String.valueOf(5.6d + 5.8d) and String.format("%f", 5.6d + 5.8d) diffrent?

String.valueOf(5.6d + 5.8d) will print "11.399999999999999".
String.format("%f", 5.6d + 5.8d) will print "11.400000".

Why is it so?

Edit: The question differs to Is floating point math broken? , because String.format() round up (see answers)

akop
  • 5,981
  • 6
  • 24
  • 51
  • Ah okay. And the "11.99999999" is just a precision-issue of double? – akop Jul 18 '18 at 12:28
  • 1
    @GhostCat I don't believe this is a duplicate, as `String.format` is different from `String.valueOf(double)` in this case due to rounding, which I believe is what OP was interested in. – Jacob G. Jul 18 '18 at 12:40
  • Yes floating point is just a finite approximation - without precision. 0.6 = 3/5 and 0.8 = 4/5 cannot be presented finitely with binary digits 0, 1. – Joop Eggen Jul 18 '18 at 12:42

2 Answers2

4

From the documentation of Format Strings for String#format:

If the precision is less than the number of digits which would appear after the decimal point in the string returned by Float.toString(float) or Double.toString(double) respectively, then the value will be rounded using the round half up algorithm.

By default, String.format("%f", ...) uses 6 decimal digits of precision; because this is fewer digits than what would appear when used by Double.toString(double) (which is equivalent to String.valueOf(double)), then the value is rounded as specified above.

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
4

There are two parts to the explanation.

  1. The result of 5.6d + 5.8d is not exactly 11.4 due to binary floating point representation, precision and rounding issues; see Is floating point math broken? for explanations of why that is so. (And no, it isn't broken!)

  2. The reason that String.valueOf and String.format are outputting different answers for the same double value is down to the respective specifications:

    For valueOf:

    "How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double."

    The double value is closer to 11.399999999999999 than 14.0 so the output is the former.

    For format:

    "If the conversion is 'e', 'E' or 'f', then the precision is the number of digits after the decimal separator. If the precision is not specified, then it is assumed to be 6."

    When you round 11.399999999999999 to 6 digits of precision after the decimal point you get 11.40000000.

(The above quotes are from the Java 9 javadocs.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216