具有积分的浮点值相等 [duplicate]

Floating point value equality with integral [duplicate]

提问人:Jonathan Woollett-light 提问时间:1/24/2018 最后编辑:Jonathan Woollett-light 更新时间:1/24/2018 访问量:73

问:

这个问题基本上归结为 2 行,第 1 行将输出 1。

std::cout << sqrt(pow(b->x - a->x, 2) + pow(b->y - a->y, 2) + pow(b->z - a->z, 2)) << std::endl;

然而,第二行将输出 0,这怎么可能?

std::cout << (sqrt(pow(b->x - a->x, 2) + pow(b->y - a->y, 2) + pow(b->z - a->z, 2)) == 1) << std::endl;

最小完整可验证示例:

struct vertice {
    double x, y, z;
    vertice(double x, double y, double z) {
        this->x = x;
        this->y = y;
        this->z = z;
    }
};

void cartDistance(const vertice * a, const vertice * b);

int main() {
    cartDistance(new vertice(0, 0, 0), new vertice(0, 0, 1));
    system("pause");
    return 0;
}

void cartDistance(const vertice * a, const vertice * b) {
    std::cout << "dist: " << sqrt(pow(b->x - a->x, 2) + pow(b->y - a->y, 2) + pow(b->z - a->z, 2)) << std::endl;
    std::cout << "dist check: " << (sqrt(pow(b->x - a->x, 2) + pow(b->y - a->y, 2) + pow(b->z - a->z, 2)) == 1) << std::endl;
}
C++ if 语句 浮点 相等

评论

2赞 Eugene Sh. 1/24/2018
它们是不同的。那么问题是什么呢?
1赞 463035818_is_not_an_ai 1/24/2018
你希望打印吗?double x = 1; std::cout << (x == 1);1
1赞 463035818_is_not_an_ai 1/24/2018
@HolyBlackCat我刚刚意识到在点击返回后 1 秒。然而,在原则上,这是误解(我猜......
1赞 463035818_is_not_an_ai 1/24/2018
@ArnavBorborah实际上这并不重要,因为在任何情况下都会返回一个浮点,并且仅仅因为在您的情况下它打印了,您就不能得出结论说它通常没问题。浮点(几乎)永远不应该与 进行比较,即使有时它似乎按预期工作sqrt1==
1赞 PaulMcKenzie 1/24/2018
如果使用整数,则不要使用整数,因为即使这样也不能保证准确。pow

答:

2赞 Richard 1/24/2018 #1

流输出运算符是舍入的,因为你真的不想看到 0.9999999999999999999997。数学是不准确的,这是对你隐瞒的。不过,比较运算符确实关心这一点。

浮点运算需要小心。

使用将允许您看到小数点后的其他数字,此时您的问题将更加明显。std::setprecision ()

评论

0赞 Jonathan Woollett-light 1/24/2018
我已经怀疑过这一点,我的问题是为什么会发生这种情况,这样存储数据似乎很荒谬,以及如何处理这个问题。
1赞 Richard Critten 1/24/2018
@JonathanWoollett轻:例如,如果你需要对货币之类的东西进行精确的数学运算,那么你就持有美分,而不是在适当大小的整数变量中。否则,您需要处理这样一个事实,即宇宙中没有足够的位来准确表示 base2 浮点数中的 0.1 (base10) 等数字。
0赞 Jonathan Woollett-light 1/24/2018
您知道任何资源来解释为什么会发生这种情况吗?根据我对使用尾数和指数的浮点值的了解,它不能简单地将 1 存储为 1 而不是一些近似值似乎是不合理的。
1赞 Richard 1/24/2018
该值在二进制中是无理的。因此,将其乘以 10 不会得到一个。您将如何设计一个存储系统,以便在有限的空间内容纳无限数量的数字?你所看到的荒谬是一个经过深思熟虑和有意的工程决定,我们从字面上建立了你所生活的世界。0.1
2赞 Eric Postpischil 1/24/2018
@Richard:.1 并非不合理。非理性是数字的属性;它独立于用于表示它们的任何基础。你的意思是 .1 不能完全以有限的二进制格式表示。