我刚刚开始研究SICP,我正在做第一个问题集,即练习1.3: “定义一个过程,它将三个数字作为参数,并返回两个较大数字的平方和。”
(define (toptwosq x y z)
(cond ((and (> x y) (> z y))) (+ (* x x) (* z z))
((and (> y x) (> z x))) (+ (* y y) (* z z))
((and (> x z) (> y z))) (+ (* x x) (* y y))))
当我运行它时,我得到了非常奇怪的结果(没有一个得到我最大两个数字的平方和)。我找到了其他有效的解决方案,我理解它们的工作原理......但为什么不采用它?
答案 0 :(得分:4)
您过早关闭了cond
条款。
((和(> xy)(> zy)))是你的第一个cond
子句,如果为true则返回#t,否则返回#f,如果为true则返回{的值{1}}成为#t。
(+(* xx)(* zz))是你的第二个cond
子句,它总是返回x的平方和z的平方之和的值,使得{{1} }语句返回该值,因为#f以外的任何值都被认为是真的。有时利用这个单部分条款是有用的,但大多数时候你想要使用两部分条款。
cond
你真的应该有一个cond
条款
(define (toptwosq x y z)
(cond ((and (> x y) (> z y)) (+ (* x x) (* z z)))
((and (> y x) (> z x)) (+ (* y y) (* z z)))
((and (> x z) (> y z)) (+ (* x x) (* y y)))))
因为到目前为止你所提出的案例都不会发现x y和z的情况相同。
获取一个进行括号匹配的编辑器,您的生活将变得更加轻松。
答案 1 :(得分:3)
正如@WorBlux指出的,你有一些括号问题。除此之外,我还有一些提示:
if
来分隔条件else
案例这就是我的意思:
(define (sumsq x y)
(+ (* x x) (* y y)))
(define (toptwosq a b c)
(if (>= a b)
(if (>= b c)
(sumsq a b)
(sumsq a c))
(if (>= a c)
(sumsq b a)
(sumsq b c))))
使用cond
可以使用以下代码编写相同的代码,注意如何以涵盖所有案例的方式正确表达条件:
(define (toptwosq a b c)
(cond ((and (>= a b) (>= b c)) (sumsq a b))
((and (>= a b) (< b c)) (sumsq a c))
((and (< a b) (>= a c)) (sumsq b a))
((and (< a b) (< a c)) (sumsq b c))))
最后一个条件可以替换为else
。这不是一个“全能”,我们确信此时不再需要考虑其他案例:
(define (toptwosq a b c)
(cond ((and (>= a b) (>= b c)) (sumsq a b))
((and (>= a b) (< b c)) (sumsq a c))
((and (< a b) (>= a c)) (sumsq b a))
(else (sumsq b c))))
最后,如果我们很聪明,我们可以摆脱一个案例(第一个和第三个案例是相同的),并进一步简化条件:
(define (toptwosq a b c)
(cond ((or (>= a b c) (and (>= a c) (> b a)))
(sumsq a b))
((and (>= a b) (> c b))
(sumsq a c))
(else (sumsq b c))))
答案 2 :(得分:0)
只是在切线上,这就是解决方案代码可以从更高阶的描述中派生。
使用等式语法,(将$
称为“of”; f x
表示应用,仅用于分组的括号,
sum_sqrs_of_biggest_two (a,b,c) = -- three arguments
= sumsqrs $ take 2 $ sort [a,b,c] -- list of three values
= sumsqrs $ take 2 $ merge (sort [a,b]) [c]
= sumsqrs $ take 2 $
if a >= b
then merge [a,b] [c]
else merge [b,a] [c]
= sumsqrs $
if a >= b
then if b >= c then [a,b] else [a,c]
else if a >= c then [b,a] else [b,c]
= if a >= b
then if b >= c then a^2+b^2 else a^2+c^2
else if a >= c then a^2+b^2 else b^2+c^2
...并将其转换回Scheme语法。