可能问题是:将浮点数与零进行比较的标准方法是什么?
据我所知,直接比较:
if ( x == 0 ) {
// x is zero?
} else {
// x is not zero??
可能会因浮点变量而失败。
我以前用过
float x = ...
...
if ( std::abs(x) <= 1e-7f ) {
// x is zero, do the job1
} else {
// x is not zero, do the job2
...
我发现here的方法相同。但我看到两个问题:
这是一个常见的比较,我想知道是否有一个标准的简短方法来做到这一点。喜欢
x.is_zero();
答案 0 :(得分:5)
没有标准的方法,因为你是否想要将一个小数字视为零,取决于你如何计算数字和它的用途。这又取决于计算引入的任何误差的预期大小,也可能取决于确定原始输入的物理测量误差。
例如,假设您的值表示某些地图软件中的行程长度(以英里为单位)。然后你很乐意将1e-7
视为等于零,因为在这种情况下它是一个非常小的数字:它是由于舍入错误或其他轻微不准确的原因而产生的。
另一方面,假设您的值代表某些电子显微镜软件中分子的大小(以米为单位)。那么你肯定不想要将1e-7
视为等于零,因为在那种情况下它是一个非常大的数字。
您应该首先考虑提供您的价值的合适准确度:错误条是什么,或者您可以合理显示多少重要数字。这将让你对使用什么样的容差进行测试,以便对零进行测试,尽管它仍然可能无法解决问题。对于地图软件,如果旅程小于某个固定值,您可以将旅程视为零,尽管该值本身可能取决于地图的分辨率。对于显微镜软件,如果两个尺寸之间的差异使得这些测量值的误差范围为零,则仍然可能 足以将它们描述为相同的尺寸。
答案 1 :(得分:4)
要将浮点值与0进行比较,只需比较它:
if (f == 0)
// whatever
这种比较没有错。如果它没有按照你的预期行事,因为f
的价值不是你想象的那样。它基本上与此问题相同:
int i = 1/3;
i *= 3;
if (i == 1)
// whatever
这种比较没有错,但i
的值不是1.几乎所有程序员都理解整数值的精度损失;很多人都不了解浮点值。
使用&#34;几乎相等&#34;而不是==
是一种先进的技术;它经常导致意想不到的问题。例如,它不是传递性的;也就是说,a
几乎等于b
且b
几乎等于c
不意味着a
几乎等于c
}。
答案 2 :(得分:2)
我不知道我的回答是否有用,我在irrlicht的irrmath.h
中找到了这个,并且至今仍在引擎的mathlib中使用它:
const float ROUNDING_ERROR_f32 = 0.000001f;
//! returns if a equals b, taking possible rounding errors into account
inline bool equals(const float a, const float b, const float tolerance = ROUNDING_ERROR_f32)
{
return (a + tolerance >= b) && (a - tolerance <= b);
}
作者通过“经过多次旋转,这是三角运算后的坐标破坏和直接比较可能导致故障”来解释这种方法。