Числа с плавающей запятой представлены внутри в виде двоичного числа, почти всегда в формате IEEE. Вы можете увидеть, как числа представлены здесь:
http://babbage.cs.qc.edu/IEEE-754/
Например, 0,25 в двоичном виде - это 0,01 b и представляется как +1,00000000000000000000000 * 2 -2 .
Хранится внутри с 1 битом для знака, восемью битами для показателя степени (представляющего значение между -127 и +128 и 23 битами для значения (ведущий 1. не сохраняется). Фактически, биты:
[0] [01111101] [+00000000000000000000000]
В то время как 0.2 в двоичном не имеет точного представления, точно так же, как 1/3 не имеет точного представления в десятичной.
Здесь проблема в том, что точно так же, как 1/2 может быть представлена точно в десятичном формате как 0,5, но 1/3 может быть приближена только к 0,3333333333, 0,25 может быть представлена точно как двоичная дробь, а 0,2 не может. В двоичном виде это 0,0010011001100110011001100 .... b , где повторяются последние четыре цифры.
Для хранения на компьютере он округляется до 0,0010011001100110011001101 b . Что действительно, очень близко, так что если вы вычисляете координаты или что-то еще, где абсолютные значения имеют значение, это нормально.
К сожалению, если вы добавите это значение к себе пять раз, вы получите 1.00000000000000000000001 b . (Или, если бы вы округлили 0,2 до 0,0010011001100110011001100 b , вместо этого вы получите 0,11111111111111111111100 b )
В любом случае, если ваше условие цикла равно 1.00000000000000000000001 b == 1.00000000000000000000000 b , оно не прекратится. Если вместо этого использовать <=, возможно, он запустится еще один раз, если значение будет чуть ниже последнего значения, но остановится. </p>
Можно было бы создать формат, который может точно представлять небольшие десятичные значения (как любое значение только с двумя десятичными знаками). Они используются в финансовых расчетах и т. Д. Но обычные значения с плавающей точкой работают так: они обменивают способность представлять некоторые небольшие «простые» числа, например, 0,2, на способность представлять широкий диапазон согласованным образом.
Обычно избегают использования числа с плавающей запятой в качестве счетчика циклов, по этой точной причине общие решения были бы:
- Если одна дополнительная итерация не имеет значения, используйте <= </li>
- Если это имеет значение, задайте вместо этого условие <= 1.0001 или какое-либо другое значение меньше вашего приращения, чтобы ошибки off-by-0.0000000000000000000001 не имели значения </li>
- Используйте целое число и делите его на что-то во время цикла
- Используйте класс, специально созданный для точного представления дробных значений
Компилятор мог бы оптимизировать цикл "=" с плавающей точкой, чтобы превратить его в то, что вы хотите, но я не знаю, разрешено ли это стандартом или когда-либо происходит на практике.