在下面的代码中,为什么与float.Epsilon进行比较而不是0?
// Coroutine to move elements
protected IEnumerator SmoothMovement (Vector3 end)
{
// Distance computation
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while(sqrRemainingDistance > float.Epsilon)
{
Vector3 newPostion = Vector3.MoveTowards(
rb2D.position, end, inverseMoveTime * Time.deltaTime
);
rb2D.MovePosition (newPostion);
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
}
答案 0 :(得分:33)
实际上,使用float.Epsilon
可能不会在这里产生任何重大差异。 float.Epsilon
是可能最小的float
大于零(大约1.401298E-45
),不意味着它是任意两个{{1}之间的最小差异}秒。由于浮点数学不精确,两个看似相等的数字之间的差异可能比float
更大。例如:
float.Epsilon
比较浮点数时,更好的做法是选择合理的值来确定两个浮点数是否“足够接近”相等。这是一个语境定义 - 例如对于距离,是1mm“足够接近”?也许在建造狗屋时,而不是电路板。你不会继续切割一块木头,直到它的长度在目标的float f1 = 1.0f / 3.0f;
float f = 1.0f;
(f1 * 3).Dump(); // 1
(f1 * 3 - f).Dump(); // 2.980232E-08
米之内。你将选择一个“足够接近”的差异来称呼它们。
对于精灵运动(我假设这是在样本中所做的) - 也许更合理的“epsilon”是可以在高分辨率监视器上表示的最小距离(或者至少会被注意到通过人眼)。
所有这一点1.401298E-45
在这里可能同样合理,因为0和sqrRemainingDistance > 0
之间没有其他数字可以是数字,但更好选择可能比float.Epsilon
大一些,以确定何时停止循环。为了获得“合理”的结果,该程序可能会循环更多的东西。
事实上,它记录在MSDN:
如果创建一个自定义算法来确定是否可以认为两个浮点数相等,则必须使用大于Epsilon常数的值来确定可接受的两个值的绝对差值,以使两个值相等。 (通常,差异幅度比Epsilon大很多倍。)
答案 1 :(得分:2)
因为floating point math is not precise。我链接的文章冗长而详细,让我用一个简单的例子来解释:
43.65 + 61.11 = 104.75999999999999
背后的原因是如何实际保存浮点数。如果你不想深入研究这个问题,请记住浮点运算的一般局限性,并且根据数学不要指望它们应该是它们应该是什么 - 包括,在这种情况下, 0