Почему значения String.valueOf(5.6d + 5.8d) и String.format("%f", 5.6d + 5.8d) различаются?
String.valueOf(5.6d + 5.8d) напечатает «11.399999999999999» .String.format("%f", 5.6d + 5.8d) напечатает «11.400000».
Почему это так?
Обновлено: вопрос отличается от Математика с плавающей запятой не работает?, потому что String.format() округляется (см. Ответы)
@GhostCat Я не верю, что это дубликат, так как String.format отличается от String.valueOf(double) в этом случае из-за округления, которое, как я считаю, было тем, что интересовало OP.
Да, с плавающей запятой - это всего лишь конечное приближение - без точности. 0,6 = 3/5 и 0,8 = 4/5 не могут быть представлены конечно двоичными цифрами 0, 1.




Из документации Строки формата для Формат строки #:
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.
По умолчанию String.format("%f", ...) использует десятичные цифры точности 6; поскольку это меньше цифр, чем могло бы появиться при использовании Double.toString(double) (что эквивалентно String.valueOf(double)), тогда значение округляется, как указано выше.
Объяснение состоит из двух частей.
Результатом 5.6d + 5.8d является не совсем 11.4 из-за двоичного представления с плавающей запятой, точности и округления; см. Математика с плавающей запятой не работает? для объяснения того, почему это так. (И нет, не сломано!)
Причина, по которой String.valueOf и String.format выводят разные ответы для того же значения double, связана с соответствующими спецификациями:
Для 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."
Значение double ближе к 11.399999999999999, чем к 14.0, поэтому на выходе получается первое.
Для 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."
Когда вы округляете 11.399999999999999 до 6 знаков точности после десятичной точки, вы получаете 11.40000000.
(Приведенные выше цитаты взяты из документации Java 9.)
Ах хорошо. А «11.99999999» - это просто результат точности двойного?