练习 1.3

Warning

这道练习的翻译有误,应该是『返回其中较大的两个数的平方和』,而不是『。。。两个数之和』。

题目要求给出的函数需要完成以下三件事:

  1. 写一个函数,接受三个数作为参数
  2. 判断三个数中较大的两个数
  3. 计算较大两个数的平方和(两个数的平方之和)

我们从后往前,一步步完成这三个任务。

平方和

计算平方和的函数可以在书本第 8 页找到:

;;; p8-sum-of-squares.scm

(define (sum-of-squares x y)
    (+ (square x) 
       (square y)))

判断大数

『判断三个数中较大的两个』这个任务实际上就是执行以下决策树(假设三个数分别为 xyz):

           x < y
          /    \
         /      \
        /        \
    x < z         y < z
     / \           / \
    /   \         /   \
x < y  x < y   y < x  y < x
x < z  z < x   y < z  z < y

这个决策树可以用 if 来表示:

(if (> x y)
    ; x 较大
    (if (> y z)
        ; x 和 y 较大
        ; x 和 z 较大)
    ; y 较大
    (if (> x z)
        ; y 和 x 较大
        ; y 和 z 较大))

也可以使用 cond

(cond ((and (> x y) (> y z))
        ; x 和 y 较大)
      ((and (> x y) (> z y))
        ; x 和 z 较大)
      ((and (> y x) (> x z))
        ; y 和 x 较大)
      ((and (> y x) (> z x))
        ; y 和 z 较大))

另一种办法是,写出 biggersmaller 两个函数,它们分别接受两个数作为参数, bigger 返回两数的较大者,而 smaller 返回两数的较小者:

;;; 3-bigger-and-smaller.scm

(define (bigger x y)
    (if (> x y)
        x
        y))

(define (smaller x y)
    (if (> x y)
        y
        x))

通过 biggersmaller ,可以用一种更抽象的方式来选出三个数中较大的两个:

(define bigger (bigger x y))
(define another-bigger (bigger (smaller x y) z))

bigger-sum-of-squares

综合以上这些工作,就可以将整个函数写出来了:

;;; 3-bigger-sum-of-squares.scm

(load "p8-sum-of-squares.scm")
(load "3-bigger-and-smaller.scm")

(define (bigger-sum-of-squares x y z)
    (sum-of-squares (bigger x y)                    ; bigger
                    (bigger (smaller x y) z)))      ; another bigger

bigger-sum-of-squares 接受三个数,并且计算较大两数的平方和。

测试:

1 ]=> (bigger-sum-of-squares 0 2 2)     ; 2^2 + 2^2 = 4 + 4 = 8

;Value: 8

1 ]=> (bigger-sum-of-squares 1 2 3)     ; 2^2 + 3^2 = 4 + 9 = 13

;Value: 13

1 ]=> (bigger-sum-of-squares 3 5 7)     ; 5^2 + 7^2 = 25 + 49 = 74

;Value: 74

讨论

blog comments powered by Disqus