何时使用机器精度,何时不使用?

4
我正在阅读一本关于渲染三维图形的书,作者有时使用“epsilon”,有时不使用。

image

注意使用 epsilon 的开头的 if 和其他未使用 epsilon 的 if

这背后的逻辑是什么?我可以看出他避免了任何除以零的可能性,但当函数不使用 epsilon 时,仍然有可能返回一个会使外部代码除以零的值。

顺便提一下,这本书是《Real-Time Rendering 3rd Edition》。


“...但是当在函数中不使用epsilon时,仍有可能返回一个值,使得外部代码除以零。” 这难道不是使用它的原因吗? - Bill the Lizard
是的,就是这样。这就是我说的。然而,作者并没有这样做。请注意其他的if语句都没有使用epsilon。 - McLovin
好的,我以为你是指在第一条语句中删除与epsilon的比较。 - Bill the Lizard
这个条件语句的另一个用途可能是避免不必要的计算。如果值 f 很小(并且可能对最终图像没有太大贡献,所以你并不在乎),你可以避免一堆浮点运算(包括极慢的除法)和分支。这是来自于光线追踪器或其他什么东西吗? - Ivan Aksamentov - Drop
这是一种射线-OBB相交测试。 - McLovin
1个回答

5

第一个语句 if(|f| > ϵ) 只是检查确保 f 与 0 显著不同。在代码中的这个特定位置进行检查很重要,因为接下来的两个语句将除以 f

其他语句不需要做到这一点,因此它们不需要使用 ϵ

例如,

if(t1 > t2) swap(t1, t2); 

交换两个数字并比较它们的自包含语句。如果错误的数字更大,则会进行交换。由于它不是用来比较一个值是否接近于0,所以不需要使用ϵ

如果从这段代码块返回的值可能导致调用代码除以零,那么应该在调用代码中处理。


那么 epsilon 应该只在本地作用域中可能存在除以零的情况下使用? - McLovin
@Pilpel 这有点像两个不同的问题。一个是 epsilon 可以用来避免被零除。另一个是像被零除这样的问题应该在适当的范围内处理。你希望编写这个函数,使其返回计算出来的任何值,然后在调用者中处理被零除的情况,如果它将使用该返回值作为分母。 - Bill the Lizard
@Pilpel 换句话说,我不知道调用此代码的人打算如何处理返回值,所以我不需要担心除以零的情况。一些调用此函数的函数可能根本不使用它进行除法运算。如果其他人需要用到除法,让他们自己处理。 - Bill the Lizard
我明白了,谢谢!如果你能回答一个小问题:假设 ab 是浮点数,并且 if(b <= a) 通过了,那么 sqrt(a-b) 是否是安全的操作,或者我需要使用epsilon? - McLovin
1
@Pilpel 因为 a-b 肯定是非负的,所以这应该是安全的。 - Bill the Lizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接