flang компилятор доказывает, что программа не зациклится 0.6.2 GitHub

Биты плавающей точки точны; неточен перевод десятичной записи в двоичную

Частая ошибка — думать, что double хранит число приблизительно. Это не так.

double, который называется «0.1», хранит точное число 3602879701896397 / 2⁵⁵. Ни малейшей неточности в битах нет. Проблема в том, что это точное число — не 0.1.

Округление произошло не при вычислении, а при чтении исходника, до всякой арифметики. 0.1 в двоичной системе — бесконечная периодическая дробь, ровно как 1/3 в десятичной, и в 52 бита мантиссы она не влезает.

Отсюда следствие, ломающее законы: каждая операция округляет заново, поэтому разные скобки дают разные точки округления:

(0.1 + 0.2) + 0.3  =  0.6000000000000001
 0.1 + (0.2 + 0.3) =  0.6

Что из этого следует практически. Смотреть на биты — значит увидеть проблему, а не решить её. Решает выбор представления: exact-in-which-base.

Чем ограничено. Речь про IEEE-754 binary64. Для типов с десятичным основанием всё иначе.

Связано: double-has-no-laws, exact-decimals-are-free