0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Common Lisp ベーシックマスター Level 12 (数値と数学)

0
Last updated at Posted at 2025-12-11

1. 数値の型

1-1. Common Lisp の数値型

Common Lisp は豊富な数値型を持つ。多くの言語では整数と浮動小数点数だけだが、Common Lisp は 有理数複素数 もネイティブにサポートする。

1-2. 整数(integer)

整数は 任意精度 をサポートする。メモリが許す限り大きな数を扱える。

;; 通常の整数
42
-17
0

;; 大きな整数も問題なし
(expt 2 100)  ; 2の100乗を計算
;; → 1267650600228229401496703205376

;; 整数の判定
(integerp 42)      ;; → T
(integerp 3.14)    ;; → NIL

1-3. 比(ratio)

分数を正確に表現 できる。計算で誤差が生じない。

;; 分数の表現
1/3                ;; → 1/3(0.333...ではない)
2/4                ;; → 1/2(自動的に約分される)

;; 分数の計算
(+ 1/3 1/6)        ;; → 1/2
(* 2/3 3/4)        ;; → 1/2

;; 比の判定
(ratiop 1/3)       ;; → T
(ratiop 2)         ;; → NIL(整数)

1-4. 浮動小数点数(float)

小数点を含む数。精度によって種類がある。

;; 浮動小数点数
3.14
-2.5
1.0e10            ; 科学的記法(1.0 × 10^10)

;; 浮動小数点数の判定
(floatp 3.14)     ;; → T
(floatp 3)        ;; → NIL

浮動小数点数の種類

精度
short-float 最低精度 1.0s0
single-float 単精度 1.0f0 または 1.0
double-float 倍精度 1.0d0
long-float 最高精度 1.0l0
;; 精度の指定
1.0f0             ; 単精度
1.0d0             ; 倍精度

;; 倍精度での計算
(* pi 2.0d0)      ;; → 6.283185307179586d0

1-5. 複素数(complex)

実数だけでは表せない数を扱うために、虚数単位 i(i² = -1)を導入した数。 実部と虚部からなり、a + bi の形で表す。√-1 のような計算や、電気工学・物理学で使われる。

;; 複素数の表現
#C(3 4)           ; 3 + 4i
#C(1.0 2.0)       ; 1.0 + 2.0i

;; 複素数の作成
(complex 3 4)     ;; → #C(3 4)

;; 実部と虚部の取得
(realpart #C(3 4))  ;; → 3
(imagpart #C(3 4))  ;; → 4

;; 複素数の計算
(+ #C(1 2) #C(3 4))  ;; → #C(4 6)
(* #C(0 1) #C(0 1))  ;; → -1(i × i = -1)

;; 複素数の判定
(complexp #C(3 4))   ;; → T

2. 型の変換と判定

2-1. 型変換関数

;; 浮動小数点数へ変換
(float 3)         ;; → 3.0
(float 1/3)       ;; → 0.33333334

;; 有理数へ変換
(rational 0.5)    ;; → 1/2
(rationalize 0.5) ;; → 1/2

;; 整数部分を取得(切り捨て)
(truncate 3.7)    ;; → 3, 0.7(2つの値を返す)
(truncate -3.7)   ;; → -3, -0.7

2-2. 型判定関数

関数 判定内容
numberp 数値か
realp 実数か
rationalp 有理数か
integerp 整数か
floatp 浮動小数点数か
complexp 複素数か
(numberp 42)      ;; → T
(numberp "42")    ;; → NIL

(realp 3.14)      ;; → T
(realp #C(1 2))   ;; → NIL

(rationalp 1/3)   ;; → T
(rationalp 3)     ;; → T(整数も有理数)

3. 基本的な算術演算

3-1. 四則演算

(+ 1 2 3)         ;; → 6(加算、複数可)
(- 10 3)          ;; → 7(減算)
(- 5)             ;; → -5(符号反転)
(* 2 3 4)         ;; → 24(乗算、複数可)
(/ 10 3)          ;; → 10/3(除算、分数になる)
(/ 10.0 3)        ;; → 3.3333333(浮動小数点)

3-2. 整数除算

;; 商と余りを同時に取得
(floor 10 3)      ;; → 3, 1(商と余り)
(truncate 10 3)   ;; → 3, 1

;; 余りだけ取得
(mod 10 3)        ;; → 1
(rem 10 3)        ;; → 1

;; mod と rem の違い(負の数の場合)
(mod -10 3)       ;; → 2(除数と同じ符号)
(rem -10 3)       ;; → -1(被除数と同じ符号)

3-3. 増減

;; 1増やす
(1+ 5)            ;; → 6
(incf x)          ; x を1増やす(破壊的)

;; 1減らす
(1- 5)            ;; → 4
(decf x)          ; x を1減らす(破壊的)

;; 任意の値で増減
(incf x 10)       ; x を10増やす
(decf x 5)        ; x を5減らす

4. 丸め関数

4-1. 4つの丸め関数

関数 丸め方向 例(3.7) 例(-3.7)
floor 負の無限大方向 3 -4
ceiling 正の無限大方向 4 -3
truncate ゼロ方向 3 -3
round 偶数丸め 4 -4
;; floor:負の無限大方向へ丸める
(floor 3.7)       ;; → 3, 0.7
(floor -3.7)      ;; → -4, 0.3

;; ceiling:正の無限大方向へ丸める
(ceiling 3.2)     ;; → 4, -0.8
(ceiling -3.2)    ;; → -3, -0.2

;; truncate:ゼロ方向へ丸める(切り捨て)
(truncate 3.7)    ;; → 3, 0.7
(truncate -3.7)   ;; → -3, -0.7

;; round:最も近い偶数へ丸める(銀行丸め)
(round 0.5)   ;; → 0, 0.5
(round 1.5)   ;; → 2, -0.5
(round 2.5)   ;; → 2, 0.5
(round 3.5)   ;; → 4, -0.5
(round 4.5)   ;; → 4, 0.5

;; 0.5 以外は通常通り最も近い整数へ
(round 1.4)   ;; → 1, 0.4
(round 1.6)   ;; → 2, -0.39999998

4-2. 2つの値を返す

丸め関数は 2つの値 を返す。商と余りである。

;; 1つ目の値だけ使う
(floor 10 3)      ;; → 3, 1

;; multiple-value-bind で両方受け取る
(multiple-value-bind (q r) (floor 10 3)
  (format t "商: ~A, 余り: ~A~%" q r))
;; → 商: 3, 余り: 1

5. 比較関数

5-1. 数値の比較

;; 等しい
(= 3 3)           ;; → T
(= 3 3.0)         ;; → T(型が違っても値が同じならT)
(= 1 1 1 1)       ;; → T(複数可)

;; 等しくない
(/= 3 4)          ;; → T
(/= 1 2 3)        ;; → T(すべて異なる)
(/= 1 2 1)        ;; → NIL(1が重複)

;; 大小比較
(< 1 2 3)         ;; → T(昇順)
(> 3 2 1)         ;; → T(降順)
(<= 1 2 2 3)      ;; → T(昇順、等しいも可)
(>= 3 2 2 1)      ;; → T(降順、等しいも可)

5-2. 符号の判定

;; 正・負・ゼロの判定
(plusp 5)         ;; → T(正)
(minusp -3)       ;; → T(負)
(zerop 0)         ;; → T(ゼロ)

;; 偶数・奇数の判定
(evenp 4)         ;; → T(偶数)
(oddp 3)          ;; → T(奇数)

6. 数学関数

6-1. 基本的な数学関数

;; 絶対値
(abs -5)          ;; → 5
(abs #C(3 4))     ;; → 5.0(複素数の絶対値)

;; 符号
(signum 10)       ;; → 1
(signum -10)      ;; → -1
(signum 0)        ;; → 0

;; 最大・最小
(max 1 5 3 2)     ;; → 5
(min 1 5 3 2)     ;; → 1

;; 最大公約数・最小公倍数
(gcd 12 18)       ;; → 6
(lcm 4 6)         ;; → 12

6-2. べき乗と平方根

;; べき乗
(expt 2 10)       ;; → 1024(2^10)
(expt 2 0.5)      ;; → 1.4142135(2^0.5 = √2)

;; 平方根
(sqrt 16)         ;; → 4.0
(sqrt 2)          ;; → 1.4142135
(sqrt -1)         ;; → #C(0.0 1.0)(虚数)

;; n乗根
(expt 8 1/3)      ;; → 2.0(3乗根)

;; 自然対数の底 e のべき乗
(exp 1)           ;; → 2.7182817(e^1)
(exp 2)           ;; → 7.389056(e^2)

6-3. 対数関数

;; 自然対数(底がe)
(log 10)          ;; → 2.302585

;; 任意の底の対数
(log 100 10)      ;; → 2.0(log10(100))
(log 8 2)         ;; → 3.0(log2(8))

;; 常用対数(底が10)の計算
(/ (log 1000) (log 10))  ;; → 3.0

6-4. 三角関数

;; 角度はラジアン
(sin 0)           ;; → 0.0
(cos 0)           ;; → 1.0
(tan 0)           ;; → 0.0

;; πを使う
(sin (/ pi 2))    ;; → 1.0(sin 90°)
(cos pi)          ;; → -1.0(cos 180°)

;; 逆三角関数
(asin 1)          ;; → 1.5707964(π/2)
(acos 0)          ;; → 1.5707964(π/2)
(atan 1)          ;; → 0.7853982(π/4)

;; atan2(2引数版)
(atan 1 1)        ;; → 0.7853982(π/4、45°)

6-5. 双曲線関数

(sinh 0)          ;; → 0.0
(cosh 0)          ;; → 1.0
(tanh 0)          ;; → 0.0

;; 逆双曲線関数
(asinh 0)         ;; → 0.0
(acosh 1)         ;; → 0.0
(atanh 0)         ;; → 0.0

7. 乱数

7-1. random 関数

;; 0以上n未満の乱数
(random 100)      ;; → 0〜99のランダムな整数
(random 1.0)      ;; → 0.0〜1.0未満のランダムな浮動小数点数

;; 範囲を指定した乱数
(+ 10 (random 11))     ; 10〜20のランダムな整数
(+ 1.0 (random 9.0))   ; 1.0〜10.0未満のランダムな浮動小数点数

7-2. 乱数の種(シード)

再現可能な乱数列を生成したい場合、*random-state* を使う。

;; 現在の乱数状態
*random-state*

;; 乱数状態を保存
(defparameter *saved-state* (make-random-state *random-state*))

;; 保存した状態から乱数を生成(再現可能)
(random 100 *saved-state*)

;; 新しい乱数状態を作成
(make-random-state t)   ; 本当にランダムな新しい状態

7-3. 乱数のユーティリティ

;; min〜maxの範囲の整数乱数
(defun random-range (min max)
  (+ min (random (1+ (- max min)))))  ; min〜maxの乱数を生成

(random-range 1 6)       ;; → 1〜6(サイコロ)

;; リストからランダムに選ぶ
(defun random-choice (lst)
  (nth (random (length lst)) lst))    ; ランダムな位置の要素を返す

(random-choice '(a b c d e))
;; → ランダムに選ばれた要素

;; リストをシャッフル(Fisher-Yates法)
(defun shuffle (lst)
  (let ((vec (coerce lst 'vector)))   ; リストをベクタに変換
    (loop for i from (1- (length vec)) downto 1
          do (rotatef (aref vec i)    ; i番目と
                      (aref vec (random (1+ i))))) ; 0〜i番目をスワップ
    (coerce vec 'list)))              ; リストに戻す

(shuffle '(1 2 3 4 5))
;; → ランダムな順序

8. ビット演算

8-1. ビット演算関数

;; ビットAND
(logand #b1100 #b1010)  ;; → 8(#b1000)

;; ビットOR
(logior #b1100 #b1010)  ;; → 14(#b1110)

;; ビットXOR
(logxor #b1100 #b1010)  ;; → 6(#b0110)

;; ビットNOT
(lognot 0)              ;; → -1

;; ビットシフト
(ash 1 4)               ;; → 16(左に4ビットシフト)
(ash 16 -2)             ;; → 4(右に2ビットシフト)

8-2. ビット操作関数

;; 特定のビットを調べる(0始まり)
(logbitp 0 5)           ;; → T(5 = #b101、0ビット目は1)
(logbitp 1 5)           ;; → NIL(1ビット目は0)

;; 立っているビット数を数える
(logcount 7)            ;; → 3(#b111)
(logcount 255)          ;; → 8

;; 整数の2進数表現
(format nil "~B" 42)    ;; → "101010"

9. 数値の表記

9-1. 異なる基数での表記

;; 2進数(#b)
#b1010                  ;; → 10

;; 8進数(#o)
#o17                    ;; → 15

;; 16進数(#x)
#xFF                    ;; → 255
#x1A2B                  ;; → 6699

;; 任意の基数(#nR)
#3R102                  ;; → 11(3進数の102)
#36Rz                   ;; → 35(36進数のz)

9-2. 数値の出力フォーマット

;; 10進数
(format nil "~D" 42)    ;; → "42"

;; 2進数
(format nil "~B" 42)    ;; → "101010"

;; 8進数
(format nil "~O" 42)    ;; → "52"

;; 16進数
(format nil "~X" 42)    ;; → "2A"

;; 浮動小数点数(固定小数点)
(format nil "~,2F" 3.14159)  ;; → "3.14"

;; 浮動小数点数(科学的記法)
(format nil "~E" 12345.6)    ;; → "1.23456E+4"

;; 桁区切り
(format nil "~:D" 1234567)   ;; → "1,234,567"

10. 実践例

10-1. 統計関数

;; 合計
(defun sum (lst)
  (reduce #'+ lst :initial-value 0))  ; 空リストでも0を返す

;; 平均
(defun mean (lst)
  (if (null lst)
      0
      (/ (sum lst) (float (length lst)))))  ; 合計÷個数

;; 分散
(defun variance (lst)
  (let ((avg (mean lst)))                   ; 平均を計算
    (mean (mapcar (lambda (x)               ; 各値と平均の差の
                    (expt (- x avg) 2))     ; 2乗の平均
                  lst))))

;; 標準偏差
(defun standard-deviation (lst)
  (sqrt (variance lst)))                    ; 分散の平方根

;; 使用例
(defparameter *data* '(2 4 4 4 5 5 7 9))
(mean *data*)               ;; → 5.0
(variance *data*)           ;; → 4.0
(standard-deviation *data*) ;; → 2.0

10-2. 数学的計算

;; 階乗
(defun factorial (n)
  (if (<= n 1)
      1
      (* n (factorial (1- n)))))  ; n × (n-1)!

(factorial 10)              ;; → 3628800

;; フィボナッチ数列
(defun fibonacci (n)
  (if (< n 2)
      n
      (+ (fibonacci (- n 1))      ; fib(n) = fib(n-1) + fib(n-2)
         (fibonacci (- n 2)))))

(fibonacci 10)              ;; → 55

;; 効率的なフィボナッチ(ループ版)
(defun fibonacci-fast (n)
  (loop repeat n                  ; n回繰り返す
        for a = 0 then b          ; a は前の b
        and b = 1 then (+ a b)    ; b は a + b
        finally (return a)))

(fibonacci-fast 50)         ;; → 12586269025

;; 素数判定
(defun primep (n)
  (and (> n 1)                    ; 1以下は素数でない
       (loop for i from 2 to (isqrt n)  ; 2から√nまで
             never (zerop (mod n i))))) ; 割り切れないことを確認

(primep 17)                 ;; → T
(primep 18)                 ;; → NIL

;; n以下の素数を列挙
(defun primes-up-to (n)
  (loop for i from 2 to n         ; 2からnまで
        when (primep i)           ; 素数なら
        collect i))               ; 収集

(primes-up-to 30)
;; → (2 3 5 7 11 13 17 19 23 29)

10-3. 金融計算

;; 複利計算
(defun compound-interest (principal rate years)
  (* principal (expt (1+ rate) years)))  ; 元本 × (1+利率)^年数

(compound-interest 1000000 0.05 10)
;; → 1628894.6(100万円を年利5%で10年運用)

;; ローン返済額(毎月)
(defun monthly-payment (principal annual-rate years)
  (let* ((monthly-rate (/ annual-rate 12))  ; 月利
         (n (* years 12))                    ; 支払い回数
         (factor (expt (1+ monthly-rate) n)))
    (* principal                             ; 元本 ×
       (/ (* monthly-rate factor)            ; 月利×(1+月利)^n ÷
          (1- factor)))))                    ; (1+月利)^n - 1

(monthly-payment 30000000 0.02 35)
;; → 約99378(3000万円、年利2%、35年ローン)

10-4. 幾何学計算

;; 2点間の距離
(defun distance (x1 y1 x2 y2)
  (sqrt (+ (expt (- x2 x1) 2)     ; (x2-x1)^2 +
           (expt (- y2 y1) 2))))  ; (y2-y1)^2 の平方根

(distance 0 0 3 4)          ;; → 5.0

;; 円の面積
(defun circle-area (radius)
  (* pi (expt radius 2)))         ; π × r^2

(circle-area 5)             ;; → 78.53982

;; 三角形の面積(ヘロンの公式)
(defun triangle-area (a b c)
  (let ((s (/ (+ a b c) 2)))      ; 半周長
    (sqrt (* s (- s a)            ; √(s(s-a)(s-b)(s-c))
             (- s b) 
             (- s c)))))

(triangle-area 3 4 5)       ;; → 6.0

;; 度からラジアンへ
(defun deg-to-rad (deg)
  (* deg (/ pi 180)))             ; 度 × π/180

;; ラジアンから度へ
(defun rad-to-deg (rad)
  (* rad (/ 180 pi)))             ; ラジアン × 180/π

(rad-to-deg (/ pi 4))       ;; → 45.0

11. 練習課題

課題1:絶対値の合計

リスト内の数値の絶対値の合計を求める関数を作れ。

(sum-abs '(-3 1 -4 1 -5))
;; → 14

解答

(defun sum-abs (lst)
  (reduce #'+ lst :key #'abs :initial-value 0))  ; 絶対値の合計

(sum-abs '(-3 1 -4 1 -5))
;; → 14

課題2:四捨五入(小数点以下n桁)

小数点以下n桁で四捨五入する関数を作れ。

(round-to 3.14159 2)
;; → 3.14

解答

(defun round-to (num digits)
  (let ((factor (expt 10 digits)))     ; 10^digits
    (/ (round (* num factor))          ; num×factor を丸めて
       (float factor))))               ; factor で割る

(round-to 3.14159 2)
;; → 3.14

課題3:最大公約数(複数引数)

任意個の整数の最大公約数を求める関数を作れ。

(gcd-multiple 12 18 24)
;; → 6

解答

(defun gcd-multiple (&rest nums)
  (reduce #'gcd nums))                 ; 順番にgcdを適用

(gcd-multiple 12 18 24)
;; → 6

課題4:二次方程式の解

二次方程式 ax² + bx + c = 0 の解を求める関数を作れ。

(quadratic 1 -5 6)
;; → (3.0 2.0)

解答

(defun quadratic (a b c)
  (let ((d (- (* b b) (* 4 a c))))     ; 判別式 b^2 - 4ac
    (cond
      ((> d 0)                          ; 2つの実数解
       (list (/ (+ (- b) (sqrt d)) (* 2 a))
             (/ (- (- b) (sqrt d)) (* 2 a))))
      ((= d 0)                          ; 重解
       (list (/ (- b) (* 2 a))))
      (t                                ; 複素数解
       (let ((real-part (/ (- b) (* 2 a)))
             (imag-part (/ (sqrt (- d)) (* 2 a))))
         (list (complex real-part imag-part)
               (complex real-part (- imag-part))))))))

(quadratic 1 -5 6)
;; → (3.0 2.0)

(quadratic 1 2 5)
;; → (#C(-1.0 2.0) #C(-1.0 -2.0))

課題5:数字の各桁の合計

整数の各桁の数字の合計を求める関数を作れ。

(digit-sum 12345)
;; → 15

解答

(defun digit-sum (n)
  (loop for c across (format nil "~D" (abs n))  ; 各桁を文字として取得
        sum (digit-char-p c)))                   ; 数値に変換して合計

(digit-sum 12345)
;; → 15

課題6:中央値

リストの中央値を求める関数を作れ。

(median '(3 1 4 1 5 9 2 6))
;; → 3.5

解答

(defun median (lst)
  (let* ((sorted (sort (copy-list lst) #'<))  ; ソート
         (len (length sorted))
         (mid (floor len 2)))                  ; 中央位置
    (if (oddp len)
        (nth mid sorted)                       ; 奇数個:中央の要素
        (/ (+ (nth (1- mid) sorted)           ; 偶数個:中央2つの平均
              (nth mid sorted))
           2.0))))

(median '(3 1 4 1 5 9 2 6))
;; → 3.5

12. まとめ

数値型

説明
整数 任意精度 42, -17
正確な分数 1/3, 2/5
浮動小数点数 小数 3.14, 1.0d0
複素数 実部+虚部 #C(3 4)

丸め関数

関数 方向
floor 負の無限大方向
ceiling 正の無限大方向
truncate ゼロ方向
round 偶数丸め

主要な数学関数

カテゴリ 関数
基本 abs, signum, max, min, gcd, lcm
べき乗・根 expt, sqrt, exp, log
三角関数 sin, cos, tan, asin, acos, atan
乱数 random

数値関数の選択

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?