Задать вопрос
Daniro_San
@Daniro_San
Программист

Почему не работает функция?

Просто покажу код.

// Собственно - это и есть проблемная функция
// Она должна превращать такие числа 0.475 в такие 475
// Короче говоря убирать дробь
int GetDotInt(double dotNum)
{
    while( dotNum > int( dotNum ))
    {
        dotNum *= 10;
    }
    return dotNum;
}

// ...

std::cout << GetDotInt ( 0.475 ) ; // Как и ожидалось 475

// А теперь удивительное (для меня) :

double number=100.475;
double dotNumber=number-100; // dotNumber == 0.475 , все правильно

std::cout<<GetDotInt(dotNumber); // Ничего, GetDotInt подвисает, цикл почему то становится бесконечным


Почему так происходит? В обоих случаях в функцию приходит одно и тоже число, но почему во втором случае цикл становится бесконечным?
И так со всеми переменными.
  • Вопрос задан
  • 180 просмотров
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 3
Nipheris
@Nipheris Куратор тега C++
Для вещественных чисел нет сравнения ==. Есть сравнения (a - b) <= eps. В большинстве случаев так и нужно, т.к. вещественными числами моделируется континуальные величины из реального мира (т.е. те, в которых не обязательно считать с точностью до каждой цифры).

С другой стороны, для денежных расчётов вещественную арифметику использовать нельзя, т.к. деньги в принципе дискретны. Никто не хочет по определению увидеть 4.74999999...$ вместо 4.75$. Для таких расчетов используются decimal-типы (таких типов не в стандартном C++, есть реализованные в виде библиотек).

Она должна превращать такие числа 0.475 в такие 475

Строго говоря, задача поставлена некорректно. Ну или бессмысленно. Такую задачу можно было бы поставить для decimal-типов, которые считаются всегда точно, и количество десятичных цифр в их записи ПРЕДСКАЗУЕМО. А для float у вас будет получаться что-то вроде 4749999999998.

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

В общем, добро пожаловать в мир машинной арифметики.

https://en.wikipedia.org/wiki/Floating_point
https://en.wikipedia.org/wiki/Decimal_data_type
Ответ написан
Комментировать
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Потому, что при работе с вещественными числами всегда надо принимать во внимание ограниченность их представления в компьютере и накопление ошибки при операциях с ними. Пройдите отладчиком свою функцию в пошаговом режиме и увидите, что при каждом умножении в дробной части остаётся небольшой хвостик, а значит условие dotNum > int(dotNum) будет всегда истинным.
Ответ написан
@lega
во втором случае цикл становится бесконечным?
Потому что в результате получается "бесконечность" в дробной части. (так работает double/float)
>>> x = 100.475
>>> x - 100
0.4749999999999943
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы