Страницы

Поиск по вопросам

вторник, 30 октября 2018 г.

Точность при вычислении

Решаю олимпиадные задачи различного рода, когда работал в Паскале никогда и не задумывался над работой оператора"=" или ">=" в работе с вещественными числами, я думал, что с точностью сравнений и проблем не может быть. Но вот я перешел на C++ и один учитель мне сказал, что "==" или ">=" нельзя использовать при работе с вещественными числами в Си, нужно писать fabs(a - b) > eps. И вот вопрос: Правда ли это? Как правильно подобрать eps? И почему же могли некоторые задачи не проходить все тесты с такой фишкой, а когда писал просто "==" они проходили. Вот конкретный пример. Задача, которая прошла после того, как я изменил LessEqual на "<=". Дано действительное число a и натуральное n. Вычислите корень n-й степени из числа a. Программа должна вывести единственное число: ответ на задачу с точностью не менее 6 знаков после запятой #include #include #include
using namespace std; const double eps = 1e-8; const double eps2 = 1e-12;
bool Equal(double a, double b) { return fabs(a - b) < eps2; }
bool lessEqual(double a, double b) { return ((a < b) || Equal(a, b)); }
double a; int n;
void solve() { double l = 0, r = a + 1, mid = 0; while (r - l > eps) { mid = (l + r) / 2; if (lessEqual(pow(mid, n), a)) l = mid; else r = mid; } printf("%.7lf", l); }
int main() { freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
scanf("%lf
", &a); scanf("%d", &n); solve();
return 0; }


Ответ

Действительно ничего хорошего из сравнения типа == при операциях с вещественными числами не выйдет. Можно попробовать простой код: double sum = 0; for ( int i = 0; i++; i < 1000000000 ) { sum += 0.000000001 } Гарантировать, что в итоге sum будет равным 1 в данном случаи невозможно. Может быть равен, а может и нет. Дело в машинной точности округления мат. операций. И ваш преподаватель все правильно говорит. Сравнение вида fabs ( 1.0 - sum ) < 0.0000000000000001; Даст верный результат всегда. ps Число 0.0000000000000001 взял просто так, но поверьте, такая ошибка вычислений очень мала, но все же точного результата ( sum == 1.0 ) вы не получите

Комментариев нет:

Отправить комментарий