提问人:Jonathan Woollett-light 提问时间:1/24/2018 最后编辑:Jonathan Woollett-light 更新时间:1/24/2018 访问量:73
具有积分的浮点值相等 [duplicate]
Floating point value equality with integral [duplicate]
问:
这个问题基本上归结为 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;
}
答:
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 不能完全以有限的二进制格式表示。
评论
double x = 1; std::cout << (x == 1);
1
sqrt
1
==
pow