Разница между valueOf () и String.format ()

Почему значения 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() округляется (см. Ответы)

Ах хорошо. А «11.99999999» - это просто результат точности двойного?

akop 18.07.2018 14:28

@GhostCat Я не верю, что это дубликат, так как String.format отличается от String.valueOf(double) в этом случае из-за округления, которое, как я считаю, было тем, что интересовало OP.

Jacob G. 18.07.2018 14:40

Да, с плавающей запятой - это всего лишь конечное приближение - без точности. 0,6 = 3/5 и 0,8 = 4/5 не могут быть представлены конечно двоичными цифрами 0, 1.

Joop Eggen 18.07.2018 14:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
734
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Из документации Строки формата для Формат строки #:

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)), тогда значение округляется, как указано выше.

Объяснение состоит из двух частей.

  1. Результатом 5.6d + 5.8d является не совсем 11.4 из-за двоичного представления с плавающей запятой, точности и округления; см. Математика с плавающей запятой не работает? для объяснения того, почему это так. (И нет, не сломано!)

  2. Причина, по которой 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.)

Другие вопросы по теме