我最近开始学习scheme,为了测试我的技能,我决定设计一个程序,打印出给定数字的所有因子。
但是,程序不会返回任何输出。我不知道原因,因为我认为我已经很好地检查了划分的条件。
这是我的密码。问题出在哪里?我无法准确定位。
(define
(factors n f)
(if (= 0 (remainder n f) )
f )
(if (< f n)
(factors n (+ f 1))))
程序的名称是因子。它需要两个输入数字:n
和f
。N
是必须为其找到因子的数字。F
是将从中打印n
的因子的数字。
您的代码中有几个错误。对于初学者来说,永远不应该有一个武装的if
表达式(也就是说,一个没有"else"部分的if
);如果发生这种情况,一些解释器会更进一步,并引发编译错误。此外,您应该使用cond
而不是嵌套if
s。
请记住,在Scheme中,所有内容都是表达式,并且必须返回一个值,但有一种情况您没有考虑:如果(>= f n)
会发生什么?这是函数逻辑中的一个漏洞,这就是我的意思:
(define (factors n f)
(if (= 0 (remainder n f))
f
(if (< f n)
(factors n (+ f 1))
; else?
)))
此外,如果要返回所有因子,则必须在递归的每个点打印它们或将它们累积在列表中,否则只返回最后一个结果。最后但并非最不重要的是,该算法根本不起作用。它需要从头开始重写。假设你只想打印结果,这个解决方案考虑了我以前的所有建议:
(define (factors n f)
(cond ((> f n) 'done)
((= 0 (remainder n f))
(display f)
(newline)
(factors n (+ f 1)))
(else
(factors n (+ f 1)))))
(factors 23174 1)
=> 1
2
11587
23174
'done
Scheme中更惯用的解决方案是返回一个包含所有值的列表,而不是一路上打印它们,使用尾部递归来获得更好的性能:
(define (factors n f)
(let loop ((f f) (acc '()))
(cond ((> f n) (reverse acc))
((zero? (remainder n f))
(loop (add1 f) (cons f acc)))
(else (loop (add1 f) acc)))))
(factors 23174 1)
=> '(1 2 11587 23174)