Различия в плавающей запятой между JDK 8 и JDK 13

Кажется, что JDK 8 и JDK 13 имеют разные числа с плавающей запятой. Я получаю JDK 8, используя Math:

cos(2.3) = -0.666276021279824

И на JDK 13:

cos(2.3) = -0.6662760212798241

Как это произошло? Разница показана на процессорах Intel 11-го поколения и AMD Ryzen с использованием Windows 10.

Изменить 20.03.2022:
Используя Long.toHexString(Double.doubleToRawLongBits()), я получаю разные битовые шаблоны:
Я получаю JDK 8:

cos(2.3) = 0xbfe5522217302fe0

И я получаю JDK 13:

cos(2.3) = 0xbfe5522217302fe1

Как вы показываете цифры?

Shawn 20.03.2022 17:55

Я использую Double.toString() для отображения результата.

Rúben Dias 20.03.2022 18:04

Добавляйте детали в виде правок к вашему Вопросу, а не в виде комментариев.

Basil Bourque 20.03.2022 18:19

Что произойдет, если вы используете StrictMath?

Louis Wasserman 20.03.2022 18:26

При использовании StrictMath результат JDK 13 совпадает с результатом JDK 8. Оки Доки.

Rúben Dias 20.03.2022 18:29

Что бы это ни стоило, используя библиотеки с произвольной точностью, мы можем показать, что точный косинус ближайшего двойного числа к 2,3 расширяется следующим образом ... 302fe09b9492 ... Таким образом, точное значение находится между двумя, ближе к выводу JDK 13.

aka.nice 21.03.2022 18:21
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
10
6
166
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Похоже, это вызвано встроенной функцией JVM для Math.cos, которая описана в соответствующей проблеме JDK-8242461. Поведение, испытанное там, не считается проблемой:

The returned results reported in this bug are indeed adjacent floating-point values [this is the case here as well]

[...]

Therefore, while it is possible one or the other of the returned values is outside of the accuracy bounds, just have different return values for Math.cos is not in and of itself evidence of a problem.

For reproducible results, use the StrictMath.cos instead.

И действительно, отключение встроенных функций с помощью -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_dcos (как предлагается в связанной проблеме) приводит к тому, что Math.cos будет иметь тот же (ожидаемый) результат, что и StrictMath.cos.

Таким образом, поведение, которое вы видите здесь, скорее всего, также соответствует документации Math.

Кроме того: мое (непрофессиональное) предположение состоит в том, что разница между Java 8 и 13 может быть связана с JDK-8143353, который изменил внутренние функции sin и cos.

Marcono1234 20.03.2022 19:22

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