Представьте, что вы работаете в базовой десятке, скажем, с 8 цифрами точности. Вы проверяете, есть ли
1/3 + 2 / 3 == 1
и узнайте, что это возвращает false
. Зачем? Ну, а реальные числа у нас есть
1/3 = 0,333 .... и 2/3 = 0,666 ....
Обрезая до восьми десятичных знаков, мы получаем
0.33333333 + 0.66666666 = 0.99999999
, что, конечно, отличается от 1.00000000
ровно 0.00000001
.
Ситуация для двоичных чисел с фиксированным числом битов в точности аналогична. В качестве действительных чисел имеем
1/10 = 0,0001100110011001100 ... (база 2)
и
1/5 = 0,0011001100110011001 ... (база 2)
Если бы мы урезали их, скажем, до семи бит, то мы получили бы
0.0001100 + 0.0011001 = 0.0100101
в то время как с другой стороны,
3/10 = 0,01001100110011 ... (база 2)
, который, усеченный до семи битов, равен 0.0100110
, и они различаются ровно 0.0000001
.
Точная ситуация немного более тонкая, потому что эти цифры обычно хранятся в научной записи. Так, например, вместо того, чтобы хранить 1/10 как 0.0001100
, мы можем сохранить его как что-то вроде 1.10011 * 2^-4
, в зависимости от того, сколько битов мы выделили для показателя степени и мантиссы. Это влияет на то, сколько цифр точности вы получите для своих расчетов.
В результате из-за этих ошибок округления вы по существу никогда не захотите использовать == для чисел с плавающей запятой. Вместо этого вы можете проверить, меньше ли абсолютное значение их разности, чем некоторое фиксированное небольшое число.