为什么我的双重比较失败了c ++

时间:2013-02-23 14:04:08

标签: c++ comparison double

我正在研究一个项目并完成它我需要与double进行一些比较,浮动...... 问题是,当我比较两个双倍时,它们分别是双倍的最大值和双倍+ 1的最大值,比较失败... 我做

if (std::max(d_max + 1.1, (d_max)) == d_max)
  std::cout << "bad" << std::endl;

函数max的答案是d_max,显示“bad”... 有人有想法或解决方案来获得我的比较精确度吗? 我检查谷歌,但我发现更多的解释,而不是真正解决我的问题... 非常感谢!

2 个答案:

答案 0 :(得分:7)

C ++中的所有对象都有一个类型。 d_max的类型为doubled_max + 1.1的类型仍然是两倍。如果d_maxdouble的最大值,则d_max + 1.1无法表示,将使用最接近的可表示值,即d_max(但是,如果添加值越大,最接近的可表示值被认为是正无穷大)。因此,您的std::max来电相当于:

std::max(d_max, d_max)

演示:

double d_max = std::numeric_limits<double>::max();
bool b = (d_max == (d_max + 1.1));
std::cout << std::boolalpha << b << std::endl;

这会将true作为输出。


在回应你的评论时,我认为你正在做这样的事情:

double d_max = std::numeric_limits<double>::max();
long double ld = d_max + 1;
std::cout << (d_max == ld) << std::endl;

奇怪的是,你发现显然d_maxld是平等的。为什么?好d_maxdouble。当您执行d_max + 1时,操作的结果也是double - d_max + 1的值无法在double中表示,如前所述,所以选择最接近的可表示值(d_max)。然后将此值分配给ld

请注意,只有确保运算符产生long double(可能带有d_max + 1.0L),才可能无法解决此问题。如此庞大的数字(大约10^308表示IEEE 754),添加1将不会将您移动到long double中的下一个可表示值。在我的实现中,我必须添加10个 289 (即1然后是289个零)才能实际导致值的变化:

double d_max = std::numeric_limits<double>::max();
long double ld = d_max + 1E289L;
std::cout << (d_max == ld) << std::endl;

此外,无法保证long double的精确度高于double。唯一的保证是它没有更少的精度。

答案 1 :(得分:1)

让我们假装双打表示为十进制浮点数,科学计数法。然后,d_max就像

9.999999999999999999 ⋅ 10⁹⁹

现在让我们添加1.1

9.999999999999999999 ⋅ 10⁹⁹ + 1.1
= 999999999999999999900000000...000 + 1.1
= 999999999999999999900000000...001.1

将那个数据调整为20,甚至是40个有效数字(你必须将这些类型,甚至是长数字,只有有限的信息容量),你得到......?好吧,再次d_max

<小时/> 请注意,同样适用于减法,因此

int main() {
  long double d_max = std::numeric_limits<double>::max();
  if(d_max == d_max - 1.1)
    std::cout << "   d_max       = " << d_max
            << "\n== d_max - 1.1 = " << d_max + 1.1 << std::endl;
  return 0;
}

输出

   d_max       = 1.79769e+308
== d_max - 1.1 = 1.79769e+308

即。这与d_max是可用的最大值无关,但它比你添加的值大得多。