일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 센서셋
- Alpha Prime(VLS-128)
- Coding Test
- VLS-128
- Phase Lock
- Reflectivity
- Frame rate
- timestamp
- Motion compensate
- PointCloud
- 3-sigma rule
- ApolloAuto
- Alpha Prime
- Single threaded
- lidar
- Veloview
- Data Packet
- Multi threaded
- Phase Offset
- Smart Pointer
- coordinate system
- PYTHON
- PointCloud Frame
- Azimuth
- Quaternion 연산
- nvidia
- object detection
- HDmap
- Interference Pattern
- Data Race
- Today
- Total
엔지니어 동행하기
std::numeric_limits<T>::epsilon(), 0에 가까운 값, Floating Point비교 본문
std::numeric_limits<T>::epsilon(), 0에 가까운 값, Floating Point비교
엔지니어 설리번 2022. 7. 10. 11:24Floating Point 가 같은지 비교할 때, == operator를 사용하면 의도하지 않은 결과를 얻게 됩니다. 그 이유는 컴퓨터가 Floating Point를 정확히 그 값으로 가지고 있는 것이 아니라 그 값과 가장 가까운, 컴퓨터로 표현할 수 있는 값으로 가지고 있기 때문입니다. 그렇다면 Floating Point가 같은지 비교하기 위해서는 어떻게 해야 하는지에 대한 내용을 정리하도록 하겠습니다.
epsilon()
epsilon() 함수는 1.0과 Type T로 나타낼 수 있는 1.0보다 큰 가장 작은 값의 차이를 출력합니다. 즉, Type T로 나타낼 수 있는 0에 가장 가까운 값을 반환합니다.
예제 1 : Floating Point가 같은 값인지 판단
epsilon()함수의 반환 값을 이용하면 Floating Point가 같은지 비교할 수 있습니다. 아래 코드의 almost_equal 함수를 그대로 이용하면 되고, Type T에는 float, double, long double 같은 type이 올 수 있습니다.
#include <cmath>
#include <limits>
#include <iomanip>
#include <iostream>
#include <type_traits>
#include <algorithm>
template<class T>
typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
almost_equal(T x, T y, int ulp)
{
// the machine epsilon has to be scaled to the magnitude of the values used
// and multiplied by the desired precision in ULPs (units in the last place)
return std::fabs(x-y) <= std::numeric_limits<T>::epsilon() * std::fabs(x+y) * ulp
// unless the result is subnormal
|| std::fabs(x-y) < std::numeric_limits<T>::min();
}
int main()
{
double d1 = 0.2;
double d2 = 1 / std::sqrt(5) / std::sqrt(5);
std::cout << std::fixed << std::setprecision(20)
<< "d1=" << d1 << "\nd2=" << d2 << '\n';
if(d1 == d2)
std::cout << "d1 == d2\n";
else
std::cout << "d1 != d2\n";
if(almost_equal(d1, d2, 2))
std::cout << "d1 almost equals d2\n";
else
std::cout << "d1 does not almost equal d2\n";
}
Output:
d1=0.20000000000000001110
d2=0.19999999999999998335
d1 != d2
d1 almost equals d2
Output을 보면, d1에 0.2를 저장해도 출력해보면 뒤쪽에 값이 더 존재하고, d2에 수식적으로 1/5를 저장해도 출력해보면 정확히 0.2와 같지 않은 것을 알 수 있습니다. 따라서 Floating Point가 같은지 비교할 때는 두 값을 빼고, eplsion() 함수를 활용해 그 차이가 0에 매우 가까운지로 판단합니다.
예제 2 : Floating Point 값이 0인지 판단
같은 맥락에서 Floating Point의 값이 0인지 판단할 때, == operator를 사용할 수 없습니다. ApolloAuto 코드에서 epsilon()함수를 활용하여 물체의 속도가 0인지 판단하고 있습니다.
// Calculate Object's velocity
constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
if (velocity < kEpsilon) {
return true; // 속도를 0으로 판단
}
https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
std::numeric_limits<T>::epsilon - cppreference.com
static T epsilon() throw(); (until C++11) static constexpr T epsilon() noexcept; (since C++11) Returns the machine epsilon, that is, the difference between 1.0 and the next value representable by the floating-point type T. It is only meaningful if std::num
en.cppreference.com
GitHub - ApolloAuto/apollo: An open autonomous driving platform
An open autonomous driving platform. Contribute to ApolloAuto/apollo development by creating an account on GitHub.
github.com
(예제 : CheckStaticHypothesisByVelocityAngleChange 함수에서 velocity가 0인지 판단할 때 사용)