0

我正在做一个项目并完成它我需要与 double、float 进行一些比较...问题是当我比较两个 double 时,它​​们分别是 double 的最大值和 double + 1 的最大值,比较失败......我愿意

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

函数 max 的答案是 d_max 并且显示“bad”......有没有人有想法或解决方案来通过我的比较获得良好的精度?我在谷歌上查了一下,但我发现了比我的问题真正解决方案更多的解释......非常感谢!

4

2 回答 2

7

C++ 中的所有对象都有一个类型。的类型d_maxdouble。的类型d_max + 1.1仍然是double。如果d_max是 a 的最大值double,则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_max奇怪的是,你发现这显然ld是平等的。为什么?嗯d_max是一个double。当你这样做时d_max + 1,操作的结果也是 a double- 的值d_max + 1不能用 a 表示double,如前所述,因此选择最接近的可表示值 ( d_max)。然后将该值分配给ld

long double请注意,仅通过确保运算符产生 a (可能带有)来解决此问题是不可能的d_max + 1.0L。对于如此庞大的数字(大约10^308使用 IEEE 754 表示),加 1 不会将您移动到 ​​a 中的下一个可表示值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。唯一的保证是它的精度不会降低。

于 2013-02-23T14:11:23.080 回答
1

让我们假设双精度数表示为十进制浮点数,科学记数法。然后,d_max会是这样的

9.999999999999999999 ⋅ 10⁹⁹

现在让我们补充1.1一下:

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

将其四舍五入到 20 位,甚至 40 位有效数字(你必须这样做,因为那些类型,即使是 long double,也只有有限的信息容量),你得到......?好吧,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,但它比您添加的价值要大得多。

于 2013-02-23T14:17:37.240 回答