Проблема в том, что формат с плавающей запятой представляет дроби в базе 2.
Первый бит дроби равен ½, второй ¼, и он имеет вид 1 / 2 n .
И проблема с в том, что состоит в том, что не каждое рациональное число (число, которое может быть выражено как отношение двух целых чисел) на самом деле имеет конечное представление в этом базовом формате 2.
(Это затрудняет использование формата с плавающей запятой для денежных значений. Хотя эти значения всегда являются рациональными числами ( n / 100), на самом деле только .00, .25, .50 и .75 имеют точные представления в любом количестве цифр двух основных дробей.
)
В любом случае, когда вы добавляете их обратно, система в итоге получает шанс округлить результат до числа, которое оно может точно представлять.
В какой-то момент он добавляет, что число .666 ... к номеру .333 ... примерно так:
00111110 1 .o10101010 10101010 10101011
+ 00111111 0 .10101010 10101010 10101011o
------------------------------------------
00111111 1 (1).0000000 00000000 0000000x # the x isn't in the final result
Крайний левый бит - это знак, следующие восемь - это показатель степени, а остальные биты - это дробь. Между показателем степени и дробью находится предполагаемое «1», которое всегда присутствует и поэтому фактически не сохраняется как нормализованный бит самой левой дроби. Я записал нули, которые на самом деле не представлены в виде отдельных битов, как o
.
Здесь много чего произошло, на каждом этапе ФПУ предпринимал довольно героические меры для округления результата. Были сохранены две дополнительные цифры точности (сверх того, что будет соответствовать результату), и FPU во многих случаях знает, был ли хотя бы один или по крайней мере 1 из оставшихся крайних правых битов одним. Если это так, то эта часть дроби больше 0,5 (в масштабе), и поэтому она округляется. Промежуточные округленные значения позволяют FPU переносить самый правый бит до целой части и, наконец, округлять до правильного ответа.
Этого не произошло, потому что кто-то добавил 0,5; FPU просто делал все возможное в рамках ограничений формата. Плавающая точка на самом деле не является неточной. Это совершенно точно, но большинство чисел, которые мы ожидаем увидеть в нашем мировоззрении с рациональными числами 10, не представлены дробной частью 2 формата. На самом деле, очень немногие.