C++98 中的浮点数比较
Float comparison in C++98
我需要写一个float比较函数(equal/not equal)但是我最多只能用C++98和boost库。我知道浮点数比较应该包括 epsilon,但我不知道如何在不使用 C++11 的情况下编写此类代码。
一个 C++98 示例:
#include <cmath>
#include <limits>
#include <iostream>
inline bool equal_with_tolerance(float a, float b, float tolerance = std::numeric_limits<float>::epsilon()) {
return std::abs(a - b) < tolerance;
}
int main() {
float a = 0.1f;
float b = 0.1000001f;
std::cout << (a == b) << '\n'; // Outputs 0.
std::cout << equal_with_tolerance(a, b) << '\n'; // Outputs 1.
}
tolerance
取决于您的问题域,使用 std::numeric_limits<float>::epsilon
很少是足够的,请参阅 this 了解更多详细信息。
I know that float comparison should include epsilon but I don't know how
您可以使用 std::numeric_limits<float>::epsilon()
获得 "machine" epsilon。
然而,浮点数相等与公差的比较并不像直接将绝对差与机器 epsilon 进行比较那么简单。任何小的 epsilon 都会将比较转化为大值的相等比较,这使您的容错度为零。
有意义的容忍比较,要求您知道您期望什么样的值、它们的大小、它们的符号、您希望容忍的预期误差。
这 blog 详细解释了这个问题。它建议跟随,这可能是合理的 "generic" 比较
bool AlmostEqualRelativeAndAbs(float A, float B,
float maxDiff, float maxRelDiff = FLT_EPSILON)
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
float diff = fabs(A - B);
if (diff <= maxDiff)
return true;
A = fabs(A);
B = fabs(B);
float largest = (B > A) ? B : A;
if (diff <= largest * maxRelDiff)
return true;
return false;
}
示例是用 C 语言编写的,但翻译成 C++ 习语很简单。文章中还有一个基于ULP的函数,但是它的实现依赖于C++中不允许的联合类型双关。
我需要写一个float比较函数(equal/not equal)但是我最多只能用C++98和boost库。我知道浮点数比较应该包括 epsilon,但我不知道如何在不使用 C++11 的情况下编写此类代码。
一个 C++98 示例:
#include <cmath>
#include <limits>
#include <iostream>
inline bool equal_with_tolerance(float a, float b, float tolerance = std::numeric_limits<float>::epsilon()) {
return std::abs(a - b) < tolerance;
}
int main() {
float a = 0.1f;
float b = 0.1000001f;
std::cout << (a == b) << '\n'; // Outputs 0.
std::cout << equal_with_tolerance(a, b) << '\n'; // Outputs 1.
}
tolerance
取决于您的问题域,使用 std::numeric_limits<float>::epsilon
很少是足够的,请参阅 this 了解更多详细信息。
I know that float comparison should include epsilon but I don't know how
您可以使用 std::numeric_limits<float>::epsilon()
获得 "machine" epsilon。
然而,浮点数相等与公差的比较并不像直接将绝对差与机器 epsilon 进行比较那么简单。任何小的 epsilon 都会将比较转化为大值的相等比较,这使您的容错度为零。
有意义的容忍比较,要求您知道您期望什么样的值、它们的大小、它们的符号、您希望容忍的预期误差。
这 blog 详细解释了这个问题。它建议跟随,这可能是合理的 "generic" 比较
bool AlmostEqualRelativeAndAbs(float A, float B,
float maxDiff, float maxRelDiff = FLT_EPSILON)
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
float diff = fabs(A - B);
if (diff <= maxDiff)
return true;
A = fabs(A);
B = fabs(B);
float largest = (B > A) ? B : A;
if (diff <= largest * maxRelDiff)
return true;
return false;
}
示例是用 C 语言编写的,但翻译成 C++ 习语很简单。文章中还有一个基于ULP的函数,但是它的实现依赖于C++中不允许的联合类型双关。