gpt4 book ai didi

c++ - 影响数字比较的双粒度c++

转载 作者:行者123 更新时间:2023-11-30 02:06:08 24 4
gpt4 key购买 nike

下面是一个测试代码块,它应该在公差范围内确定 2 个 double 的等价性。

double lhs_1 = 0.02;
double lhs_2 = 0.04;
double rhs = 0.03;
double tolerance = 0.01;

bool is_match_1 = (abs(lhs_1 - rhs) <= tolerance);
bool is_match_2 = (abs(lhs_2 - rhs) <= tolerance);

但是 is_match_2 结果为假,而 is_match_1 结果为真。我知道存储在计算机中的数字是离散值而不是连续的。有人可以分享解决方案吗?我宁愿在合理的范围内通过考试。有没有办法将 double 的值增加 1,无论它当前具有什么精度(我不熟悉 double 的位布局)?因为我可能只是增加容差值以解决此粒度问题。

编辑:

当这真正实现时,用户将定义输入和公差,所以我只是试图为他们输入的任何值提供预期的输出。

最佳答案

不幸的是,选择公差没有“好的”规则。

您可以随意使用“机器 epsilon”

double epsilon = std::numeric_limits<double>::epsilon()

这是与 1 相加后得到与 1 不同的结果的最小值。

我通常将公差写成 epsilon 的函数。没有好的规则,但是比如这样比较

bool fuzzy_equals(double a, double b)
{
static const double eps = std::numeric_limits<double>::epsilon();
return std::fabs(b - a) < 1024 * eps * std::max(a, b);
}

在许多情况下效果很好。你可以调整 1024,我喜欢二的幂,但你可能不喜欢。您选择的实际值取决于问题。 doubles 的 Epsilon 大约是 10^-16,所以 1024 非常小,在很多情况下你需要一个更大的数字 (实际上任何操作,包括 fuzzy_equals 中的减号操作都会“吃掉"一个 epsilon -- 它们可以抵消,但平均而言,n 操作意味着 sqrt(n) * epsilon 精度,因此 1024 对应于一百万次操作后的预期精度)

在其他情况下,精度不是很好,例如当根据已知值测试函数的最小值时(最小值通常只确定到 sqrt(eps) 精度),我使用

bool fuzzy_equals2(double a, double b)
{
static const double eps = std::numeric_limits<double>::epsilon();
return std::fabs(b - a) < 1024 * std::sqrt(eps) * std::max(a, b);
}

我经常使用其他函数,例如 std::pow(eps, something),甚至 -1/std::log(eps)。这取决于我可以从问题中获得哪些先验信息,以及我预期的错误是什么。

在代码结构方面,我使用函数式方法并将比较器 传递给我的算法,有点像STL 谓词。这使您不必将比较逻辑硬编码到您的算法中。

简而言之,没有万能的规则。你要根据问题来选择

关于c++ - 影响数字比较的双粒度c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9010341/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com