为什么这个尾递归函数要复杂得多?
Why Is This Tail-Recursive Function So Much More Complicated?
所以,我正在研究一些基础数学,我想要一个函数来转换基数。
我写了这个函数:
(define (convert-base from to n)
(let f ([n n])
(if (zero? n)
n
(+ (modulo n to) (* from (f (quotient n to)))))))
它适用于我所有的个人测试 < base 10,并且据我所知,如果我只是添加对额外数字的支持,那么它对于测试 > base 10 的功能非常好。
让我感到困惑的是,当我试图使函数尾递归时,我最终陷入了混乱(为了 SO 的好处,我添加了一些间距,因为我的代码通常不清晰或不漂亮):
;e.g. 10 2 10 should output 1010, 10 8 64 should output 100 etc.
(define (convert-base-tail from to n)
(let f ([n n]
[acc 0]
[zeros 0])
(begin (printf "n is ~a. acc is ~a. zeros are ~a.\n" n acc zeros)
(cond [(zero? n) (let exp
([x acc]
[shft zeros])
(if (zero? shft)
x
(exp (* x 10) (- shft 1))))]
[(zero? (modulo n to))
(if (zero? acc)
(f (quotient n to) (* acc from) (add1 zeros))
(f (quotient n to) (* acc from) zeros))]
[else (f (quotient n to) (+ (* acc from) (modulo n to)) zeros )]))))
我的问题本质上是,为什么尾递归函数要复杂得多?由于问题的性质,这是不可避免的,还是由于我的疏忽?
不是,真的:
(define (convert-base from to n)
(let f ([n n] [mul 1] [res 0])
(if (zero? n)
res
(f (quotient n to) (* mul from) (+ res (* mul (modulo n to)))))))
测试
> (convert-base-y 10 2 10)
1010
> (convert-base-y 10 8 64)
100
所以,我正在研究一些基础数学,我想要一个函数来转换基数。
我写了这个函数:
(define (convert-base from to n)
(let f ([n n])
(if (zero? n)
n
(+ (modulo n to) (* from (f (quotient n to)))))))
它适用于我所有的个人测试 < base 10,并且据我所知,如果我只是添加对额外数字的支持,那么它对于测试 > base 10 的功能非常好。
让我感到困惑的是,当我试图使函数尾递归时,我最终陷入了混乱(为了 SO 的好处,我添加了一些间距,因为我的代码通常不清晰或不漂亮):
;e.g. 10 2 10 should output 1010, 10 8 64 should output 100 etc.
(define (convert-base-tail from to n)
(let f ([n n]
[acc 0]
[zeros 0])
(begin (printf "n is ~a. acc is ~a. zeros are ~a.\n" n acc zeros)
(cond [(zero? n) (let exp
([x acc]
[shft zeros])
(if (zero? shft)
x
(exp (* x 10) (- shft 1))))]
[(zero? (modulo n to))
(if (zero? acc)
(f (quotient n to) (* acc from) (add1 zeros))
(f (quotient n to) (* acc from) zeros))]
[else (f (quotient n to) (+ (* acc from) (modulo n to)) zeros )]))))
我的问题本质上是,为什么尾递归函数要复杂得多?由于问题的性质,这是不可避免的,还是由于我的疏忽?
不是,真的:
(define (convert-base from to n)
(let f ([n n] [mul 1] [res 0])
(if (zero? n)
res
(f (quotient n to) (* mul from) (+ res (* mul (modulo n to)))))))
测试
> (convert-base-y 10 2 10)
1010
> (convert-base-y 10 8 64)
100