Деление числа с плавающей запятой на 10

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

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

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

Итак, мой код примерно такой,

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

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

Но этого не произошло, вместо этого появляется что-то вроде 0,100000000001. И я был похож на "Что за черт!"

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


person Shane Hsu    schedule 24.12.2011    source источник
comment
Вы делите его на 1, а не на 10.   -  person Pubby    schedule 24.12.2011
comment
Это довольно очевидная опечатка.   -  person Shane Hsu    schedule 24.12.2011
comment
Вам также следует прочитать: Что должен знать каждый компьютерный ученый о перемещении - Точечная арифметика.   -  person AusCBloke    schedule 24.12.2011
comment
Шейн: Пожалуйста, не перепечатывайте содержание здесь. Скопировать и вставить. Люди очень расстраиваются и опускаются, когда обнаруживают, что потратили пятнадцать минут на отладку проблемы, которой никогда не существовало. (Ну, Я расстраиваюсь и отказываюсь от ответа. Другие могут отреагировать лучше.)   -  person sarnold    schedule 24.12.2011
comment
Вместо этого вы можете разделить на 2 (или 8), если это вариант, который даст вам несколько более точные значения.   -  person Kerrek SB    schedule 24.12.2011


Ответы (2)


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

unsigned int div = 1;
while(...)
{
    double step = 1.0 / (double)div;
    ....
    div *= 10;
}
person thomas    schedule 24.12.2011
comment
div, вероятно, также должен быть типом с плавающей запятой, иначе вы далеко не уйдете с этим. - person Kerrek SB; 24.12.2011

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

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

person Raymond Hettinger    schedule 24.12.2011