为什么我的SICP练习1.3的解决方案不起作用?

时间:2013-07-23 00:31:49

标签: scheme sicp

我刚刚开始研究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))))

当我运行它时,我得到了非常奇怪的结果(没有一个得到我最大两个数字的平方和)。我找到了其他有效的解决方案,我理解它们的工作原理......但为什么不采用它?

3 个答案:

答案 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语法。