因此,假设我们有一个浮点类型 XType,其中有两个数字:
XType const a = 1.2345
XType const b = 1.2300
然后我想要一个函数 IsClose(XType const f1,XType const f2,unsigned const truncated_figures) 这样
// the numbers are equal if the last two figures are ignored (1.23 == 1.23)
IsClose<XType>(a,b,2) == true
// the numbers are not equal if only the last is ignored (1.234 != 1.230)
IsClose<XType>(a,b,1) == false
到目前为止,我遇到了这个丑陋的烂摊子,但我还没有说服自己这是正确的:
// check if two floating point numbers are close to within "figures_tolerance" figures of precision for the applicable type
template <typename FloatType>
bool const IsClose(FloatType const f1, FloatType const f2, unsigned const figures_tolerance)
{
FloatType const tolerance_exponent = std::pow(10.0,figures_tolerance);
FloatType const tolerance =
std::pow(tolerance_exponent,std::log10(f1)) *
std::numeric_limits<FloatType>::epsilon()
;
return std::abs(f1 - f2) < tolerance;
}
我的推理是,容差应该是将 epsilon 提高到数量超过或低于 1.0 的数量级(epsilon 所基于的有效数字)。这有意义吗?有没有更好、更可靠的方法?
编辑:我使用模板函数的解决方案如下(它基于 user763305 的回答如下)
// check if two floating point numbers are within the last n digits of precision for the
// largest of the two numbers being compared.
template <typename FloatType>
bool const IsWithinPrecision(FloatType const f1, FloatType const f2, unsigned const n = 1U)
{
FloatType const f_ref = std::max(std::abs(f1), std::abs(f2));
FloatType const distance = std::abs(f1 - f2);
FloatType const e = std::numeric_limits<FloatType>::epsilon();
return distance < std::pow((FloatType) 10.0, (FloatType) n) * e * f_ref;
}