Деление поплавка на 10

Возможный дубликат:
Почему десятичные числа не могут быть представлены точно в двоичном формате?

Я разрабатываю довольно простой алгоритм использования математики под C++.

И у меня есть переменная с плавающей точкой с именем "step", каждый раз, когда я заканчиваю цикл while, мне нужно делить шаг на 10.

Так что мой код вроде этого,

float step = 1;
while ( ... ){
      //the codes
      step /= 10;
}

По моей глупой простой логике, это хорошо кончается. Шаг будет разделен на 10, от 1 до 0,1, от 0,1 до 0,01.

Но это не так, вместо этого появляется что-то вроде 0.100000000001. И я был как "Что, черт возьми"

Может кто-нибудь, пожалуйста, помогите мне с этим. Вероятно, это что-то в самом типе данных, которое я не совсем понимаю. Так что, если кто-то может объяснить дальше, это будет оценено.

2 ответа

Решение

Это численная проблема. Проблема в том, что 1/10 - это бесконечное длинное число в двоичном коде, и последующее применение деления на 10 заканчивается суммированием ошибки на каждом шаге. Чтобы получить более стабильную версию, вы должны умножить делитель. Но будьте осторожны: результат тоже не точный! Вы можете заменить поплавок на двойной, чтобы минимизировать ошибку.

unsigned int div = 1;
while(...)
{
    double step = 1.0 / (double)div;
    ....
    div *= 10;
}

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

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

Другие вопросы по тегам