比较浮点数的奇怪结果

Weird results comparing floats

我有以下代码(printfs用于调试)

float maximum = max(num1, max(num2, num3));
float other1 = min(num1, min(num2, num3));
float other2 = num1 + num2 + num3 - other1 - maximum;
//Now we know the maximum is maybe the hypothenuse

printf("Max %f, other %f, other %f\n", maximum, other1, other2);
printf("%f %f %f\n", pow(other1, 2), pow(other2, 2), pow(maximum, 2));
printf("%d\n", (pow(other1, 2) + pow(other2, 2)) == pow(maximum, 2));
return(pow(other1, 2) + pow(other2, 2) == pow(maximum, 2));

我想做的是检查 3 个数字是否是毕达哥拉斯三元组。那么,当输入数字 3、4 和 5 时,它 returns 0.

我不知道为什么会出现这种情况。我很确定问题出在比较上,但我不明白哪里出了问题...

非常感谢您的帮助!谢谢!

假设您的数学是正确的,那么问题出在浮点数比较上。因为浮点数和双精度数不会产生 "exact" 结果,所以简单地使用“==”比较是行不通的。

相反,您需要执行以下操作:

// if the difference between the two is very small they are basically equivalent
if fabs(a - b) < 0.00001

有关如何正确比较浮点数的更多说明,请参阅此答案:

Comparing floating point numbers in C

引用 Eric Postpischil's answer to Why is my integer math with std::pow giving the wrong answer?:

All the other answers so far miss or dance around the one and only problem in the question: The pow in your C++ implementation is poor quality. It returns an inaccurate answer when there is no need to.

Get a better C++ implementation, or at least replace the math functions in it.

另见 Pascal Cuoq's answer to std::pow with integer parameters, comparing to an integer type and http://blog.frama-c.com/index.php?post/2013/04/06/Non-experts-need-accurate-floating-point-the-most

这对您的应用程序来说可能有点过头了,但如果您不介意使用开源和稳定的库,GSL 有一个名为 int gsl_fcmp (double x, double y, double epsilon) 的函数,它将两个双精度浮点数与任何所需的 epsilon (准确性)。这考虑了比 fabs() 更强大的算法的相对准确性。它也非常适合测试您的代码。

编译时将gsl和link安装到库中。与您的其他包括,添加

#include <gsl/gsl_math.h>

那么你的代码就是

float maximum = max(num1, max(num2, num3));
float other1 = min(num1, min(num2, num3));
float other2 = num1 + num2 + num3 - other1 - maximum;
//Now we know the maximum is maybe the hypothenuse

printf("Max %f, other %f, other %f\n", maximum, other1, other2);
printf("%f %f %f\n", pow(other1, 2), pow(other2, 2), pow(maximum, 2));
int is_comparable = (0 == gsl_fcmp (pow(other1, 2) + pow(other2, 2), 
                                    pow(maximum, 2), 0.00001));
printf("%d\n", is_comparable);
return is_comparable;

编辑

我应该补充一点,GSL 代表 GNU Scientific Library