数値の等価性を判定する場合、通常は eq、eql、equal
といった非数値比較述語ではなく、=
を使用すべきです。異なる浮動小数点オブジェクトや大きな整数オブジェクトであっても、数値的に等しくなることがあります。eq を使用してこれらを比較する場合、それらが同一の オブジェクト
であるかどうかを判定します。一方、eql や equal を使用する場合は、その値が 区別不能
であるかどうかを判定します。これに対し、= は数値比較を行い、非数値比較では nil が返されるような場合に t
を返すことがあり、その逆も同様です。浮動小数点の基礎
を参照してください。
Emacs Lispでは、2つの固定数値が数値的に等しい場合、それらは同じLispオブジェクトとなります。つまり、固定数値においては eq は =
と等価です。未知の値と固定数値を比較する場合、eq
を使うのが便利なことがあります。というのも、eq
は未知の値が数値でない場合でもエラーを報告せず、あらゆる型の引数を受け付けるからです。対照的に、=
は引数が数値またはマーカーでない場合にエラーを発生させます。しかし、整数の比較であっても、可能であれば = を使用するのがより良いプログラミング作法です。
数値を eql や equal
と比較すると便利な場合があります。これらは、2つの数値が同じデータ型(ともに整数、またはともに浮動小数点数)かつ同じ値である場合に、それらを等しいとみなします。これに対し、= は整数と浮動小数点数を等しいとみなすことがあります。等価述語 を参照してください。
もう一つ注意点があります。浮動小数点演算は厳密ではないため、浮動小数点値の等価性を判定するのは得策ではないことが多いです。通常は、近似的な等価性を判定する方が適切です。そのための関数を以下に示します。
(defvar fuzz-factor 1.0e-6)
(defun approx-equal (x y)
(or (= x y)
(< (/ (abs (- x y))
(max (abs x) (abs y)))
fuzz-factor)))
この関数は、すべての引数が数値的に等しいかどうかを判定し、等しい場合は t を、そうでない場合は
nil を返します。
この関数は、両方の引数が数値である場合を除き、eq
と同様に動作します。数値を型と数値値で比較するため、(eql 1.0 1) は nil を返しますが、(eql 1.0 1.0) と
(eql 1 1) はともに t
を返します。これにより、小さな整数だけでなく大きな整数の比較も可能です。符号、指数、仮数部が同一の浮動小数点数は eql となります。これは数値比較とは異なります。(eql 0.0
-0.0) は nil を返し、(eql
0.0e+NaN 0.0e+NaN) は t を返しますが、= はその逆の動作をします。
この関数は、引数が数値的に等しいかどうかを判定し、等しくない場合は t を、等しい場合は nil を返します。
この関数は、各引数が後続の引数よりも厳密に小さいかどうかを判定します。条件を満たす場合は t
を、そうでない場合は nil を返します。
この関数は、各引数が次の引数以下であるかどうかを判定します。該当する場合は t を、そうでない場合は
nil を返します。
この関数は、各引数が後続の引数よりも厳密に大きいかどうかを判定します。条件を満たす場合は t
を、そうでない場合は nil を返します。
この関数は、各引数が次の引数以上であるかどうかを判定します。条件を満たす場合は t
を、そうでない場合は nil を返します。
この関数は、引数のうち最大のものを返します。
(max 20)
⇒ 20
(max 1 2.5)
⇒ 2.5
(max 1 3 2.5)
⇒ 3
この関数は、引数のうち最小のものを返します。
(min -4 1)
⇒ -4
この関数は number の絶対値を返します。