03.05 - 관계 연산자 (Relational operators)
C++ 에는 여섯 가지 관계 연산자(relational operator) (or 비교 연산자)가 있다.
Operator |
Symbol |
Form |
Operation |
Greater than |
> |
x > y |
true if x is greater than y, false otherwise |
Less than |
< |
x < y |
true if x is less than y, false otherwise |
Greater than or equals |
>= |
x >= y |
true if x is greater than or equal to y, false otherwise |
Less than or equals |
<= |
x <= y |
true if x is less than or equal to y, false otherwise |
Equality |
== |
x == y |
true if x equals y, false otherwise |
Inequality |
!= |
x != y |
true if x does not equal y, false otherwise |
위 연산자들은 상당히 직관적인 기호다. 각 연산자눈 부울 값(bool value) true(1)
또는 false(0)
를 반환한다.
위 연산자들은 정수 비교 시 간단하게 사용할 수 있다:
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int x;
std::cin >> x;
std::cout << "Enter another integer: ";
int y;
std::cin >> y;
if (x == y)
std::cout << x << " equals " << y << "\n";
if (x != y)
std::cout << x << " does not equal " << y << "\n";
if (x > y)
std::cout << x << " is greater than " << y << "\n";
if (x < y)
std::cout << x << " is less than " << y << "\n";
if (x >= y)
std::cout << x << " is greater than or equal to " << y << "\n";
if (x <= y)
std::cout << x << " is less than or equal to " << y << "\n";
return 0;
}
And the results from a sample run:
Enter an integer: 4
Enter another integer: 5
4 does not equal 5
4 is less than 5
4 is less than or equal to 5
부동 소수점 숫자 비교 (Comparison of floating point values)
관계 연산자를 사용해서 부동 소수점 숫자를 비교하는 것은 위험하다. 부동 소수점 숫자의 반올림 오류 때문에 예상치 못한 결과가 나타날 수 있기 때문이다.
오류의 예:
#include <iostream>
int main()
{
double d1(100 - 99.99);
double d2(10 - 9.99);
if (d1 == d2)
std::cout << "d1 == d2" << "\n";
else if (d1 > d2)
std::cout << "d1 > d2" << "\n";
else if (d1 < d2)
std::cout << "d1 < d2" << "\n";
return 0;
}
위 프로그램은 예상치 못한 결과를 출력한다.
d1 > d2
위 프로그램은 d1 = 0.0100000000000005116
, d2 = 0.0099999999999997868
이다. 두 숫자는 0.01
에 가깝지만, d
이 d2
보다 크다.
부동 소수점 숫자에 연사자 ==
또는 !=
를 사용하는 것은 권장하지 않는다. 부동 소수점 숫자가 같은지 평가하는 가장 일반적인 방법은 두 값이 얼마나 가까운 지 계산하는 함수를 만드는 것이다. 두 숫자가 "충분히 가깝다면" 같다고 평가한다. "충분히 가깝다"를 평가하는데 사용하는 값은 전통적으로 epsilon이라고 한다. epsilon은 일반적으로 소수(Ex. 0.0000001)로 정의한다.
보통 다음과 같이 함수를 작성한다:
#include <cmath>
bool isAlmostEqual(double a, double b, double epsilon)
{
return fabs(a - b) <= epsilon;
}
<cmath>
라이브러리의 fabs()
함수는 매개 변수의 절댓값을 반환하는 함수다.
그러나 위 함수는 효율적이지 못하다. 0.00001
epsilon
은 1.0
에는 적합하지만, 0.0000001
에는 너무 크고 10,000
과 같은 숫자에는 너무 작다. 이것은 함수를 호출할 때마다 입력에 적합한 epsilon
을 선택해야 한다는 걸 의미한다.
유명한 컴퓨터 과학자인 Donald Knuth는 다음과 같은 방법을 사용했다.
#include <cmath>
bool approximatelyEqual(double a, double b, double epsilon)
{
return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
}
int main()
{
if (approximatelyEqual(a, b, 0.001))
std::cout << a << " is equals " << b << "\n";
return 0;
}
위 함수가 어떻게 동작하는지 알아보자. 위 함수에서 "충분히 가깝다"는 a와 b중 큰 것의 1%내에 있다는 것을 의미한다.
approximatelyEqual()
함수는 잘 작동하지만, 숫자가 0에 가까워질수록 완벽하지는 않다.
#include <iostream>
int main()
{
double a = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;
std::cout << approximatelyEqual(a, 1.0, 1e-8) << "\n";
std::cout << approximatelyEqual(a-1.0, 0.0, 1e-8) << "\n";
}
Perhaps surprisingly, this returns:
1
0
위 프로그램에서 두 번째 코드가 예상대로 수행되지 않는다. 이같은 문제를 피하는 한 가지 방법은 첫 번째 방식의 absolute epsilon
과 Donald Knuth 방식의 relative epsilon
을 사용하는 것이다.
bool approximatelyEqualAbsRel(double a, double b, double absEpsilon, double relEpsilon)
{
double diff = fabs(a - b);
if (diff <= absEpsilon)
return true;
return diff <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * relEpsilon);
}
위 알고리즘은 새로운 매개 변수 absEpsilon
을 추가했다. 먼저 a
와 b
사이의 거리가 absEpsilon
보다 작은지 확인하다. 이 값은 매우 작은 값(Ex. e0-12
)으로 설정해야 한다. 이런 a
와 b
가 모두 0
에 가까운 경우를 처리한다. 그 다음 Donald Knuth의 알고리즘으로 돌아간다.
#include <iostream>
int main()
{
double a = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;
std::cout << approximatelyEqual(a, 1.0, 1e-8) << "\n";
std::cout << approximatelyEqual(a-1.0, 0.0, 1e-8) << "\n";
std::cout << approximatelyEqualAbsRel(a-1.0, 0.0, 1e-12, 1e-8) << "\n";
}
1
0
1
approximatelyEqualAbsRel()
은 작은 입력값도 올바르게 처리한다
이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/35-relational-operators-comparisons/ 입니다.