我正在做一个项目,为了完成它,我需要与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,并且显示"坏"。。。有人有想法或解决方案可以通过我的比较获得良好的精度吗?我在谷歌上查了一下,但我发现了更多的解释,而不是我问题的真正解决方案。。。非常感谢!
C++中的所有对象都有一个类型。d_max
的类型为double
。d_max + 1.1
的类型仍然是双重的。如果d_max
是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
时,运算的结果也是double
——尽管如上所述,d_max + 1
的值不能在double
中表示,因此选择了最接近的可表示值(d_max
(。然后将该值分配给ld
。
请注意,这不太可能通过确保运算符产生long double
(可能是d_max + 1.0L
(来解决。在如此巨大的数字下(用IEEE 754表示的10^308
附近(,加1不会移动到long double
中的下一个可表示值。在我的实现中,我必须添加10289(即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
更高的精度。唯一的保证是它的精度不会低于。
让我们假设双精度表示为十进制浮点数,科学表示法。那么,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
是可用的最大值无关,而是它比您添加的值大得多。