我听说我的显卡版本的CUDA不支持递归,这是我的路径跟踪器大量使用的东西。在
< >我在Python和C++中都对它进行了编码,我会发布一些简化的Python代码,以便于阅读:def Trace(ray):
hit = what_object_is_hit(ray)
if not hit:
return Color(0, 0, 0)
newRay = hit.bouceChildRayOffSurface(ray)
return hit.diffuse * (Trace(newRay) + hit.emittance)
我尝试手动展开函数,结果是一个确定的模式(d
是diffuse
,而{
不过,我可能错了。。。在
我的问题是,如何在while
循环中实现这段代码?在
我想用这种形式:
total = Color(0, 0, 0)
n = 1
while n < 10: # Maximum recursion depth
result = magical_function()
if not result: break
total += result
n += 1
我以前从来没有真正处理过分解递归函数的任务,所以任何帮助都将不胜感激。谢谢!在
你真走运。您的代码使用尾部递归,也就是说,当您在函数中使用递归时。编译器通常可以为您执行此操作,但您必须在此处手动执行:
通常,您可以始终使用堆栈来表示递归。在
例如:
本质上,递归的工作原理是将函数的参数推送到堆栈上,然后用新的参数再次调用函数。你只需要使用堆栈来模拟这个。在
在递归函数中,每次递归调用发生时,调用方的状态都被保存到堆栈中,然后在递归调用完成时恢复。要将递归函数转换为迭代函数,需要将挂起函数的状态转换为显式数据结构。当然,您可以在软件中创建自己的堆栈,但通常可以使用一些技巧来提高代码的效率。在
这个答案贯穿于本例的转换步骤。您可以对其他循环应用相同的方法。在
尾递归变换
让我们再看看您的代码:
一般来说,递归调用必须返回到调用函数,这样调用者才能完成它所做的工作。在这种情况下,调用者通过执行加法和乘法来“完成”。这会产生一个类似}。请注意,本系列中的第一项仅指迭代1,第二项仅指迭代1和2,依此类推。这告诉我们我们可以动态地计算这个级数。此外,这个系列包含序列
^{pr2}$d1 * (d2 * (d3 * (... + e3) + e2) + e1))
。我们可以利用加法的分配律和乘法与加法的结合律将计算转化为{(d1, d1*d2, d1*d2*d3, ...)
,我们也可以动态计算。把它放回代码里:尾递归消除
在新循环中,调用者在被调用者完成后没有工作要做;它只是返回被调用者的结果。调用者没有工作要完成,所以它不必保存任何状态!代替调用,我们可以覆盖旧参数并返回函数的开头(不是有效的Python,但它说明了这一点):
最后,我们将递归函数转换成一个等价循环。剩下的就是用Python语法来表达它。在
相关问题 更多 >
编程相关推荐