博主头像
zzh

ワクワク

2.1.1实例:有理数的算术运算

这个实例最展现了一种复合的方法(cons),让我们能够操作抽象的元素。最主要的是掌握其思想:愿望性思维。作为开始,我们假设已经有了一种构造有理数的方法(构造函数)和取得各个元素的方法(选择函数)。在这个基础上构造了有理数的加减乘除。在完成了这一部分之后,我们再转头去实现有理数的底层实现。这样很自然地,我们就把有理数的实现与其支持的方法隔离的开来,构造了一层抽象屏障。

#lang sicp
#;(再实现有理数的运算之前,先假定我们已经有了构造函数make-rat,其把第一个参数作为分子,第二个参数作为分母,返回一个有理数;选择函数numer,接受一个有理数参数,返回分子;demon接受一个有理数,返回分母。在这个基础上构造加减乘除)

;;有理数加法
(define (add-rat x y) 
  (make-rat (+ (* (numer x) (demon y))
               (* (demon x) (numer y)))
            (* (demon x) (demon y))))
            
;;有理数减法
(define (sub-rat x y)
 (make-rat (- (* (numer x) (demon y))
               (* (demon x) (numer y)))
            (* (demon x) (demon y))))
            
;;有理数乘法
(define (mul-rat x y)
  (make-rat (* (numer x) (numer y))
            (* (demon x) (demon y))))
            
;;有理数除法
(define (div-rat x y)
   (make-rat (* (numer x) (demon y))
            (* (demon x) (numer y))))
            
;;有理数相等判断
(define (equal-rat? x y)
  (= (* (numer x) (demon y))
     (* (demon y) (numer x))))
     
;;有理数表达
(define (print-rat x)
  (newline)
  (display (numer x))
  (display "/")
  (display (demon x)))
  
#;(以上我们就完成了有理数支持的操作,接下来完成有理数的实现)

;;有理数构造
(define (make-rat x y)
  (let ((g (gcd x y)))
    (cons (/ x g) (/ y g))))
    
;;取出分子
(define (numer x)
  (car x))
  
;;取出分母
(define (demon x)
  (cdr x))

#;(在实际使用时,我们会发现效果不如预期。这是因为我们再拿到一个有理数时,会下意识地对它进行化简分子分母同时除于最大公因数。为此我们需要一个得到最大公因数的方法。GCD方法能够实现这个功能。以下是对其算法的简述:
如果r是a/b的余数,那么我们可以得到:
GCD(a,b)=GCD(b,r)。
同时加上终止条件,b=0时余数是a.
)

;;gcd的实现
(define (gcd a b)
  (if (= b 0)
      a
      (gcd b (remainder a b))))
      
#;(完成这个部分后,只需要对make-rat进行修改就可以了,完全不用修改加减乘除等方法。这也体现了抽象屏障的优势)      

;;以下都是测试用例
(define onehalf (make-rat 1 2))
(print-rat onehalf)
(define onethird (make-rat 1 3))
(print-rat (add-rat onehalf onethird))
(print-rat (mul-rat onehalf onethird))
(print-rat (add-rat onethird onethird))
  
2.1.1实例:有理数的算术运算
https://zzhygs.cn/index.php/archives/36/
本文作者 zzh
发布时间 2024-09-16
许可协议 CC BY-NC-SA 4.0
发表新评论