我认为double的精确度导致了这个问题,正如在类似帖子中描述的那样,但我想知道是否有办法实现正确的结果。我正在使用比较两个参数的函数模板,如果它们相等则返回true。
template <class T>
bool eq(T one, T two)
{
if (one == two)
return true;
else
return false;
}
它适用于eq(0.8,0.8),但它不适用于eq(0.8 * 0.2,0.16)。正如我所提到的,我认为它与双精度有关,因为它也适用于int eq(8 * 2,16)。
答案 0 :(得分:18)
首先,您应该阅读这些文章中的一个(或两个):What Every Computer Scientist Should Know About Floating-Point Arithmetic和The Perils of Floating Point。
如果您正在寻找模板的解决方案,我建议您使用template specialization来处理T==double
和T==float
的情况。
答案 1 :(得分:5)
你应该很少尝试比较双打的平等。相反,您需要决定您愿意接受的误差范围:
return fabs(one - two) <= 0.000001
答案 2 :(得分:3)
您需要重载函数,然后进行适合浮点的比较:
bool eq(double one, double two)
{
// You'll want to choose a delta that is appropriate for your usage
return fabs(one - two) < DELTA;
}
你还想为float做另一个重载。
答案 3 :(得分:2)
这是关于比较浮点数的问题的另一个article。
比较平等
浮点数学并不准确。像0.2这样的简单值无法使用二进制浮点数精确表示,浮点数的有限精度意味着操作顺序的微小变化可能会改变结果。不同的编译器和CPU架构以不同的精度存储临时结果,因此结果将根据您的环境的详细信息而有所不同。如果您进行计算,然后将结果与某些预期值进行比较,那么您很可能无法获得预期的结果。
答案 4 :(得分:1)
在不指定精度的情况下,不应该比较浮点数。
这将返回false:
cout << (0.8 * 2 < 0.16 ? true : false) << endl;
但这将返回true:
cout << ((0.8 * 2 - 0.16) < 0.001 ? true : false) << endl;
答案 5 :(得分:0)
您始终可以使用舍入功能来确定。