Clang float infinity, разделенный на бесконечность, дает другой результат с флагом оптимизации

Я только что обнаружил, что при делении числа с плавающей запятой на бесконечность при компиляции с любым параметром оптимизации получается другое значение NaN для clang.

std::numeric_limits<float>::infinity()/std::numeric_limits<float>::infinity()

приводит к следующим наборам битов:

  • 01111111110000000000000000000000 при компиляции с -O1 и
  • 11111111110000000000000000000000 при компиляции без него.

Разница только в знаковом бите.

Я предполагаю, что решение о том, как представлять NaN, зависит от компилятора, но я удивлен, что мы увидим разные представления в одном и том же компиляторе. GCC и MSVC кажутся согласованными (11111111110000000000000000000000) независимо от оптимизации.

Мои вопросы:

  1. Должны ли мы ожидать согласованного результата для всех компиляторов независимо от оптимизации?
  2. Должны ли мы ожидать стабильного результата в рамках одного компилятора независимо от оптимизации?

🤔 А знаете ли вы, что...
C++ обладает множеством инструментов для отладки и профилирования кода.


2
70
1

Ответ:

Решено
  1. Должны ли мы ожидать согласованного результата для всех компиляторов независимо от оптимизации?

  2. Должны ли мы ожидать стабильного результата в рамках одного компилятора независимо от оптимизации?

Поведение, о котором вы сообщаете для Clang и других компиляторов, соответствует как C++, так и IEEE-754, даже если знаковый бит меняется от обстоятельства к обстоятельству, как показано ниже.

Сканирование стандарта C++ (проект N4849 2020 г.) не показывает ничего, что определяло бы, каким должен быть знак результата NaN.

C++ не требует, чтобы реализации соответствовали IEEE-754. Тем не менее, если предположить, что реализация это делает, то IEEE-754 2019 (проект D2.47, март 2019 г.) 6.3 «Знаковый бит» говорит:

… Для всех остальных операций в настоящем стандарте знак не указывается бит результата NaN, даже если имеется только один входной NaN или когда NaN получен из недопустимого значения. операция…

«все остальные операции» включают в себя деление, поскольку до этого обсуждались операции copy, negate, abs, copySign, totalOrder и isSignMinus.