在下面的代码中,为什么会有与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;
}
}
发布于 2015-05-13 22:02:45
实际上,使用float.Epsilon
在这里可能不会有任何显著的区别。float.Epsilon
是大于零的最小可能的float
(大致为1.401298E-45
),这并不意味着它是任意两个float
之间的最小差。由于浮点数学是不精确的,所以两个看似相等的数字之间的差可能比float.Epsilon
大得多。例如:
float f1 = 1.0f / 3.0f;
float f = 1.0f;
(f1 * 3).Dump(); // 1
(f1 * 3 - f).Dump(); // 2.980232E-08
在比较浮点数时,更好的做法是选择一个合理的值来确定两个浮点数是否“足够接近”相等。这是一个上下文定义--例如,对于距离,1 1mm是否“足够近”?也许是在建狗屋的时候,但不是电路板的时候。你不会一直切割一块木头,直到它的长度在目标的1.401298E-45
米之内。你要选择一个“足够接近”的差值来表示它们是相等的。
对于sprite运动(我假设这就是在示例中所做的)-也许更合理的"epsilon“是高分辨率监视器上可以表示的最小距离(或者至少是人眼可以注意到的)。
总而言之,sqrRemainingDistance > 0
在这里可能也是合理的,因为在0和float.Epsilon
之间没有其他数字可以是这个数字,但更好的选择可能是比Epsilon
大得多的数字来确定何时停止循环。为了得到一个“合理”的结果,程序可能会进行更多的循环。
事实上,它在MSDN上有文档记录
如果您创建自定义算法来确定是否可以将两个浮点数视为相等,则必须使用大于ε常量的值来建立可接受的绝对差值,才能将这两个值视为相等。(通常,这种差异的幅度比Epsilon大很多倍。)
发布于 2015-05-13 22:07:32
因为floating point math is not precise。我链接的文章很长很详细,所以让我用一个简单的例子来解释:
43.65+61.11=104.75999999999999
背后的原因是浮点数实际上是如何保存的。如果您不想深入研究这个问题,只需记住浮点算术的一般限制,并且不要期望它们完全符合数学原理--包括,在本例中为0。
https://stackoverflow.com/questions/30216575
复制相似问题