Scheme事始め12:数学的な例を関数を作りながらみてみる(1)

  • インクレメントとデクレメント
> (define ++ (lambda (i) (+ i 1)))
> (++ 3)
4
> (define -- (lambda (i) (- i 1)))
> (-- 5)
4
> (define ** (lambda (a b) (expt a b)))
> (** 2 3)
8
  • 割り算関係。商、剰余、法数
> (define // (lambda (a b) (quotient a b)))
> (// 23 4)
5
> (define /@ (lambda (a b) (remainder a b)))
> (/@ 23 4)
3
> (define /: (lambda (a b) (remainder a b)))
> (/: 23 4)
3
  • 整数の偶奇判断
> (define parity-of
    (lambda (p)
      (if (odd? p) -1 1)))
> (parity-of 3)
-1
> (parity-of 6)
1
> (parity-of 4.3)
. . odd?: contract violation
  expected: integer
  given: 4.3
  • 変数の入れ替えでa-bb-aに、a^bb^aになどをする。演算子を与える形にする
> (define proc-swap
    (lambda (proc a b)
      (let* ((dummy a) (a b) (b dummy))
        (proc a b))))
> (proc-swap - 3 4)
1
> (- 3 4)
-1
> (proc-swap / 3 4)
1 1/3
> (/ 3 4)
3/4
> (proc-swap ** 2 3)
9
> (** 2 3)
8
  • 四捨五入
    • 組み込み関数でいかにも四捨五入っぽい関数roundは次のように「一番近い整数だけれど、ちょうど真ん中だったら偶数を返す」というちょっと困るルールになっているという
> (round 1.5)
2.0
> (round 2.5)
2.0
    • この不具合を解消するために、与えた値の絶対値以下であってかつそれに一番近い整数を返すという組み込み関数truncateを使って、任意のケアでの四捨五入を定義したのが以下。与えるのは四捨五入したい値と桁数。四捨五入したい値の正負で調整のために加える値を\pm \frac{1}{2}に分け、桁数に応じて倍して加えて除して元に戻す
> (define adjust-of
    (lambda (x digit)
      (let ((slide (if (positive? x) 1/2 -1/2)))
        (/ (truncate (+ slide (* x digit))) digit) )))
> (adjust-of 1.2994 100)
1.3
> (adjust-of 1.2994 1000)
1.299
> (adjust-of 1.2994 10)
1.3
> (adjust-of 1.2994 10000)
1.2994
> (adjust-of -1.2994 10)
-1.3
> (adjust-of -1.2994 100)
-1.3
> (adjust-of -1.2994 1000)
-1.299
> (adjust-of -1.2994 10000)
-1.2994
  • 2つの値の範囲である値から初めて等間隔の数列を発生させてみる。Rで言えば
seq(from=a,to=b,by=t)
> (define seq-by
    (lambda (a b t)
      (if (> a b)
          '()
          (cons a (seq-by (+ a t) b t)) )))
> (seq-by 1 5 1)
(1 2 3 4 5)
> (seq-by 1 5 0.7)
(1 1.7 2.4 3.0999999999999996 3.8 4.5)
> (seq-by 1 5 1/3)
(1 1 1/3 1 2/3 2 2 1/3 2 2/3 3 3 1/3 3 2/3 4 4 1/3 4 2/3 5)
    • ただし、aからtずつ増やしてbを越える手前まで、というルールなので、b-aの符号とtの符号が一致していないと終わらなくなる、その点のケアをしたのが以下の関数定義(符号が合わない場合には、最初の値のみを返す)
> (define seq-by2
(lambda (a b t)
(if(> (* (- b a) t) 0)

(if (> a b)
'()
(cons a (seq-by (+ a t) b t)) )
(cons a '())
)))

> (seq-by2 1 5 0.7)
(1 1.7 2.4 3.0999999999999996 3.8 4.5)
> (seq-by2 1 5 -0.7)
(1)