如何修改gforth的fibsum实现以正确使用返回栈?
如何在Gforth中使用返回栈实现Fibonacci序列求和?
学习Gforth时,我已经用多种方式实现了Fibonacci序列,下面是计算指定阶数内所有Fibonacci值之和的fibsum的三种实现。Fibonacci序列为:0 1 1 2 3 5 8 13 21 34 55 89,fibsum的输出序列为:0 1 2 4 7 12 20 33 54 88 ....
第一种实现(循环式,依赖全局变量)
variable fbsum : fibsum ( u -- u.sum ) { p } 0 1 \ Fibonacci-Sum. \ This sums the first u values of the Fibonacci sequence. 0 fbsum ! p 0= if drop dup else 1 fbsum ! endif p 1 u+do over over + dup fbsum +! rot drop loop 2drop fbsum ? ;
第二种实现(递归+循环,依赖全局变量)
variable fbsum : fibsum2x ( u -- u.sum ) { p } 0 1 \ Fibonacci recursive (1) p dup 1 > if dup 1- recurse swap 2 - recurse + nip nip else p 1 = if 1 fbsum +! endif \ Here p matches the argument to the top call! nip nip endif ; : fibsum2 ( u -- u.sum ) \ Fibonacci-Sum. \ This sums the first u values of the Fibonacci sequence. { m } 0 fbsum ! m 1+ 1 u+do i fibsum2x drop loop fbsum ? ;
第三种实现(递归+循环,依赖全局变量)
variable fbsum : fibsum3x ( u -- u.sum ) { p } 0 1 \ Fibonacci recursive (2) p dup 1 > if dup 1- recurse swap 2 - recurse + nip nip else \ p 1 = if 1 fbsum +! endif \ Here p matches the argument to the top call! nip nip endif ; : fibsum3 ( u -- u.sum ) \ Fibonacci-Sum. \ This sums the first u values of the Fibonacci sequence. { m } 0 fbsum ! m 1+ 1 u+do i fibsum3x fbsum +! loop fbsum ? ;
可以看到我的代码未使用返回栈,且尝试使用时失败,请问如何修改上述代码以正确使用返回栈?
修改方案:用返回栈替代全局变量,实现无状态求和
返回栈在Forth中用于临时存储数据,避免数据栈被递归或循环操作打乱,核心操作包括:
>r:将数据栈顶元素压入返回栈r>:将返回栈顶元素弹出到数据栈r@:读取返回栈顶元素,不弹出
1. 循环式实现(用返回栈存累加和)
移除全局变量fbsum,用返回栈维护累加状态:
: fibsum ( u -- sum ) { p } p 0= if drop 0 exit then \ 0阶和为0 p 1= if drop 0 exit then \ 1阶只有0,和为0 0 1 \ 初始化前两个Fib数:a=0, b=1 1 >r \ 返回栈存入初始累加和(0+1=1) p 2 u+do over over + dup \ 计算下一个Fib数c=a+b,复制一份用于累加 r@ + >r \ 累加和 += c,更新返回栈 rot drop \ 调整栈:将a替换为b,b替换为c loop 2drop r> \ 清理栈上的a、b,取出最终累加和 ;
2. 递归式实现(用返回栈存递归参数)
用返回栈保存递归过程中的阶数参数,避免数据栈混乱,同时直接返回求和结果:
: fib-r ( n -- fib ) dup 0= if drop 0 exit then dup 1= if drop 1 exit then 1>r \ 将当前n压入返回栈暂存 1- recurse \ 计算fib(n-1) r> 2- recurse + \ 取出n,计算fib(n-2)并求和得到fib(n) ; : fibsum ( u -- sum ) dup 0= if drop 0 exit then dup 1= if drop 0 exit then 1>r \ 暂存当前u fib-r \ 计算fib(u) r> 1- fibsum + \ 取出u,求和sum(u-1) + fib(u) ;
修改核心要点
- 彻底移除全局变量
fbsum,用返回栈存储累加和或临时参数,代码更简洁且无副作用 - 递归场景中,用
>r暂存当前阶数,避免递归调用覆盖数据栈上的关键值 - 循环场景中,用
r@读取当前累加和,>r更新累加状态,替代全局变量的+!操作
内容的提问来源于stack exchange,提问作者Michel
相关产品推荐
相关产品推荐

