Когсуэлл Джефф
Шрифт:
Решение
Напишите свои функции сравнения, которые принимают в качестве параметра ограничение точности сравнения. Пример 3.6 показывает основную методику, используемую в такой функции сравнения.
Пример 3.6. Сравнение чисел с плавающей точкой
#include <iostream>
#include <cmath> // для fabs
using namespace std;
bool doubleEquals(double left, double right, double epsilon) {
return (fabs(left - right) < epsilon);
}
bool doubleLess(double left, double right, double epsilon,
bool orequal = false) {
if (fabs(left - right) < epsilon) {
// В рамках epsilon, так что считаются равными
return (orequal);
}
return (left < right);
}
bool doubleGreater(double left, double right, double epsilon,
bool orequal = false) {
if (fabs(left - right) < epsilon) {
// В рамках epsilon, так что считаются равными
return (orequal);
}
return (left > right);
}
int main {
double first = 0.33333333;
double second = 1.0 / 3.0;
cout << first << endl;
cout << second << endl;
// Тест на прямое равенство. Не проходит тогда, когда должно проходить.
// (boolalpha печатает булевы значения как "true" или "false")
cout << boolalpha << (first == second) << endl;
// Новое равенство. Проходит так, как требуется в научном приложении.
cout << doubleEquals(first, second, .0001) << endl;
// Новое меньше чем
cout << doubleLess(first, second, .0001) << endl;
// Новое больше чем
cout << doubleGreater(first, second, .0001) << endl;
// Новое меньше чем или равно
cout << doubleLess(first, second, .0001, true) << endl;
// Новое больше чем или равно
cout << doubleGreater(first, second, .0001, true) << endl;
}
Далее показан вывод этого примера.
0.333333
0.333333
false
true
false
false
true
true
Обсуждение
Код примера 3.6 начинается с двух значений — 0.33333333 и того, что компьютер получает в результате деления 1.0 / 3.0. Он с помощью форматирования по умолчанию
cout
печатает эти два значения. Они кажутся одинаковыми и равными 0.333333. Однако при сравнении этих двух значений они оказываются различными. Значение 1.0 / 3.0 имеет больше значащих цифр, чем 0.33333333, и, следовательно, как полагает машина, эти два числа не равны. Однако в некоторых приложениях может потребоваться, чтобы они считались равными. Чтобы добиться этого, надо написать собственные функции сравнения чисел с двойной точностью:
doubleLess
, doubleEquals
и doubleGreater
, каждая из которых принимает в качестве параметров два значения типа double
. Кроме того, doubleLess
и doubleGreater
имеют дополнительный параметр, который при его равенстве true
приводит к тому, что эти функции ведут себя как «меньше или равно» и «больше или равно» соответственно. Чтобы заставить эти функции учитывать точность, рассмотрим функцию
doubleEquals
. Вместо того чтобы проверять на равенство, эта функция проверяет, находится ли разность двух чисел в указанном пользователем диапазоне epsilon
. (В качестве epsilon
пример использует значение 0.0001.) Если это так, то функция возвращает значение true, что означает, что значения одинаковы. Таким образом, равными окажутся значения 0.3333, 0.33333, 0.333333, 0.33333333333 и 0.33333323438.