当两个相等的双精度的相对比较不起作用时,我该怎么办?
What should I do when relative comparison of two equal doubles doesn't work?
我使用相对比较,因为它在这里描述。 我有两个双打。其中第一个是计算结果:
double d1(callComputation() );
第二个定义如下:
double d2(0.009);
我对近似相等的实现返回错误,这是正确的,因为:
std::printf("d1 = %25.20fn", d1);
指纹:
d1 = 0.00900000000000011902
和
std::printf("d2 = %25.20fn", d2);
指纹:
d2 = 0.00899999999999999932
我预计 d2 将大致表示如下:
0.00900000000000011239 or 0.00900000000000000000 etc
并且比较 d1 和 d2 的结果将为真。但即使大约平等也不合适。在这种情况下,我应该如何比较? 我不需要高精度的计算,但显然我对 计算结果的稳定性。也许点后固定数量的数字(例如两个(将有助于解决这个问题?
首先,这是最接近.0009
的值,可以表示为双精度 IEEE 浮点数。
每个浮点运算都可能导致舍入运算。 基于 Epsilon 的策略对于确定两个浮点计算是否表示"相同"的实数并不可靠。
在一般情况下,确定两个计算是否产生相同的实数实际上是不可计算的;您可以将 Halt 减少到它。
确定它们是否相等的"最佳"最昂贵的通用方法是区间数学。 用一对代表间隔的双打代替你的双打。 在每次计算中,确保上双精度的结果向上舍入,下双精度的结果向下舍入(除法/减法时,请确保不要翻转区间,因为除法/减法是单调递减的;乘以负数也是如此(。 如果将包含 0 的区间除以包含 0 的区间,请确保两个值都变为 NaN,如果除以包含 0 的区间,则结果为 +inf 到 -inf。
区间数学有一些问题;它很昂贵(远远超过2倍(,需要用控制向上/向下舍入的操作替换每个基元运算,你会发现在大量的数学运算之后,区间最终变得惊人地大。
传统的 IEEE 舍入生成的值通常更接近您想要的值,因为它实际上随机舍入每次迭代。 如果您掷硬币 10,000 次,您将获得一个平均值为 5000、方差为 2500、标准差为 50 的随机值;所以97%的时间你会在4900到5100,99%+在4850到5150。 每个舍入操作实际上是一枚硬币添加 + 或 - epplsion/2(实际上更好;它添加一个介于 +/- epsilon/2 之间的值,被选为最小的值(,因此在 10k 操作后,可能的误差小于 +/- 75*epsilon。 同时,区间数学将声明某个误差为 +/-10000 epsilon。
TL;博士
你需要一个更大的厄普西隆。
- 比较字符串的 GetLine 工作一次,然后比较之后不起作用
- 为什么当我们使用等于'='符号比较器函数时,c ++的内置排序函数不起作用?
- C 自定义比较器不起作用
- 伯克利数据库 Db->get 使用自定义比较函数时不起作用
- c++ 比较在缓冲区的 2 个字符串之间不起作用
- 为什么INT(char)的比较不起作用
- 排序功能不起作用(字符串比较问题)
- 为什么数组之间的==相等比较不起作用
- 为什么字符数组之间的这种比较不起作用?
- 我的自定义比较不起作用
- C++ 标准::查找自定义比较器不起作用
- 带有自定义比较器的映射不起作用
- 在 qt 中比较字符串不起作用
- std::排序和比较模板功能不起作用
- 我的字符串比较在 CPP 中不起作用
- 对的比较功能不起作用
- GNU使ifeq比较不起作用
- 为什么比较方法不起作用?
- std::使用函数作为比较器进行排序,不起作用
- 矢量元素和 txt 文件行之间的字符串比较不起作用