| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Точность чисел с плавающей запятой |
| Автор: IKM2007 14.5.2008, 16:51 | ||||
| Добрый день всем, ответьте вот на такой вопрос. Как выполняется прибавление или убавление чисел типа double. Вот на примере.
то есть условие (4.2-3.2<2.2-1.2) верно. Но вот...
то есть ни одно условие не верно. Может кто нибудь обяснит мне, что здесь творится? |
| Автор: rrrFer 14.5.2008, 17:09 | ||||
| ИМХО парадокс интересно что:
a 4.2000000000000002 double b 3.2000000000000002 double c 2.2000000000000002 double d 1.2000000000000000 double вообще погрешности большие почему-то: если написать
то в функцию f передано: a 1.2000000000000000 double b 0.20000000000000001 double c 1.3000000000000000 double d 0.29999999999999999 double |
| Автор: anatox91 14.5.2008, 17:20 |
| мдаа.. попробовал - действительно... |
| Автор: rrrFer 14.5.2008, 17:49 | ||
а еще вот что получилось:
при вводе числа 2.5 все нормально, погрешности не видно вообще, а вот если ввести 1.2.... |
| Автор: JackYF 14.5.2008, 18:58 | ||||
Феерическая фигня. Перевод в строковую форму занимает туеву хучу процессорного времени. Сравнение чисел с плавающей точкой можно сравнивать только с учётом допуска некой малой величины E. То есть, к примеру:
Само собой, E выбирается в зависимости от нужной точности и алгоритма. |
| Автор: nickless 14.5.2008, 19:17 | ||||||
Просто сравнивать надо с погрешностью эпсилон, например так:
Просто числа хранятся в двоичном виде, по этому число 1.2 = 1 + 1/5 точно представить невозможно, можно только приближенно. Например в double точность мантиссы 52 бит, т.е. погрешность будет где-то +- 0.5 * 1/(2^52) ~ 1.110223e-16 |
| Автор: archimed7592 14.5.2008, 19:25 |
| Ещё, варианты: 1. Написать класс-обёртку над double(в идеале, над произвольным типом T), который будет проделывать операции сравнения с заданной точностью автоматически. 2. Использовать арифметику с бесконечной точностью(т.н. exact types): GMP, boost::rational, CGAL::Quotient, CGAL::Gmpzf(обёртка над gmp_mpf_class) и пр. 3. Использовать арифметику с неограниченной, но, задаваемой точностью(преимущество в том, что в отличии от exact types с ними можно проделывать такие операции, по определению невозможные для exact types как то sin, cos, sqrt, etc.): MPFR, mpfr::Real(С++ обёртка из MPFR_CPP). Ссылки на все вышеупомянутые классы/библиотеки можно нарыть в гугле. ЗЫ. Помню, как лет 5 назад я матерился на Delphi, когда обнаружил в нём "ошибку" из-за которой иногда получается отрицательный ноль из-за чего не работала вычислительная часть одного из моих проектов На самом деле - это всего лишь отрицательное бесконечно малое, которое, кстати тоже является почвой для долгих поисков мифического бага |
| Автор: IKM2007 14.5.2008, 20:14 |
| Всем Большое Спасибо, все понятно. |
| Автор: xvr 15.5.2008, 11:39 | ||
Сугубо точности ради |
| Автор: archimed7592 15.5.2008, 12:44 | ||
Если мне не изменяет память, этот самый отрицательный ноль и интерпретируется как отрицательное бесконечно малое... Разве нет? |
| Автор: xvr 15.5.2008, 13:25 | ||||||
Нет.
Integer - implied (not stored) |