比较 C++ 中的两个浮点变量

Compare two float variables in C++

本文关键字:两个 浮点变量 C++ 比较      更新时间:2023-10-16

我已经阅读了多篇关于浮点变量比较的文章,但未能理解并从这些文章中获得所需的知识。所以,我在这里发布这个问题。

比较两个浮点变量的好方法是什么? 下面是代码片段:

#define EPSILON_VALUE 0.0000000000000001
bool cmpf(float A, float B)
{
return (fabs(A - B) < EPSILON_VALUE);
}
int main()
{
float a = 1.012345679, b = 1.012345678;
if(cmpf(a, b))cout<<"same"<<endl;
else cout<<"different"<<endl;
return 0;
}

输出:same,尽管两个浮点变量保存不同的值。

没有通用的解决方案来比较包含先前操作错误的浮点数。必须使用的代码是特定于应用程序的。因此,要获得正确的答案,您必须更具体地描述您的情况。

根本问题是,使用不正确的数据执行正确的计算通常是不可能的。如果你想计算两个精确数学值xy的函数,但你拥有的唯一数据是一些不精确计算的值xy,通常不可能计算出完全正确的结果。例如,假设您想知道x+y的总和是多少,但您只知道x是 3,y是 4,但您不知道真实的、精确的xy是什么。然后,您无法计算x+y

如果您知道xy大约xy,那么您可以通过添加xy来计算x+y 的近似值。当正在计算的函数(在本例中+)具有合理的导数时,工作:稍微改变具有合理导数的函数的输入会稍微改变其输出。当您要计算的函数具有不连续性或较大的导数时,此操作将失败。例如,如果要使用近似x计算x的平方根(在实域中),但由于先前的舍入误差x可能是负数,则计算sqrt(x)可能会产生异常。同样,比较不等式或顺序是一个不连续的函数:输入的微小变化可以完全改变答案(从错误到真实,反之亦然)。

常见的坏建议是与"宽容"进行比较。此方法将假阴性(如果比较确切的数学值,则满足比较的数字的错误拒绝)换成误报(不正确接受不满足比较的数字)。

适用者是否可以容忍虚假接受取决于应用程序。因此,没有通用的解决方案。

要设置的容差级别,甚至计算容差的性质,都取决于数据、误差和先前的计算。因此,即使可以与公差进行比较,使用的公差量以及如何计算公差也取决于应用。没有通用的解决方案。

输出:相同,尽管两个浮点变量保存不同的值。

"浮点变量持有不同的值"是没有根据的。

打印same是因为即使初始化常量不同,a,b值也相同。


典型的float是 32 位,可以表示大约 232个不同的值,例如 1.0、1024.0、0.5、0.125。 这些值的形式均为:+/- some_integer*2some_integer

1.0123456791.012345678不在那个float集中。 @Rudy维尔特胡伊斯。

1.012345 67165374755859375 // `float` member
1.012345 678
1.012345 679
1.012345 790863037109375   // `float` member

类似的情况也适用于double,但精度更高 - 通常为64位。

1.0123456791.012345678也不在该double集中

1.012345 67799999997106397131574340164661407470703125    // `double` member
1.012345 678
1.012345 6780000001931085762407747097313404083251953125  // `double` member
...
1.012345 6789999998317597373898024670779705047607421875  // `double` member
1.012345 679
1.012345 67900000005380434231483377516269683837890625    // `double` member

可以将其视为四舍五入的 2 个步骤。 代码1.012345679四舍五入到最接近的double1.012345679000000005380434231483377516269683837890625。 然后,赋值将double舍入到最接近的float1.01234567165374755859375。

float a = 1.012345679;
// 'a' has the value of 1.01234567165374755859375

同样对于b.代码1.012345678四舍五入到最接近的double1.012345677999999997106397131574340164661407470703125。 然后,赋值将double舍入到最接近的float1.01234567165374755859375。

flaot b = 1.012345678;
// 'b' has the value of 1.01234567165374755859375

ab具有相同的值。

这是因为浮点数具有 7 位精度。 如果你想要更好的精度,你需要使用双倍或长双倍。