Решаю олимпиадные задачи различного рода, когда работал в Паскале никогда и не задумывался над работой оператора"=" или ">=" в работе с вещественными числами, я думал, что с точностью сравнений и проблем не может быть. Но вот я перешел на C++ и один учитель мне сказал, что "==" или ">=" нельзя использовать при работе с вещественными числами в Си, нужно писать fabs(a - b) > eps. И вот вопрос:
Правда ли это?
Как правильно подобрать eps?
И почему же могли некоторые задачи не проходить все тесты с такой фишкой, а когда писал просто "==" они проходили.
Вот конкретный пример. Задача, которая прошла после того, как я изменил LessEqual на "<=". Дано действительное число a и натуральное n. Вычислите корень n-й степени из числа a. Программа должна вывести единственное число: ответ на задачу с точностью не менее 6 знаков после запятой
#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 ) вы не получите
Комментариев нет:
Отправить комментарий