要判断数值是否相等,通常应使用 =,而不是 eq、eql、equal 这类非数值比较谓词。不同的浮点数对象或大整数对象,在数值上可能相等。如果用 eq 比较,判断的是它们是否为同一个 对象;如果用 eql 或 equal,判断的是它们的值是否 indistinguishable不可区分;而 = 采用纯数值比较,有时会在非数值比较返回 nil 时返回 t,反之亦然。See 浮点数基础。
在 Emacs Lisp 中,如果两个定长数(fixnum)数值相等,它们就是同一个 Lisp 对象。也就是说,对定长数而言,eq 等价于 =。有时用 eq 把未知值与定长数比较会更方便,因为即使未知值不是数字,eq 也不会报错 —— 它接受任意类型的参数。相比之下,如果参数不是数字或标记(marker),= 会抛出错误。不过,只要可以,即使是比较整数,更好的编程习惯仍是使用 =。
有时用 eql 或 equal 比较数字会很有用:只有当两个数类型相同(同为整数或同为浮点数)且值相同时,它们才被视为相等。而 = 可以把一个整数和一个浮点数视为相等。See 相等性谓词。
还有一个细节:由于浮点数运算不精确,直接判断浮点数是否相等通常是不合适的。一般更好的做法是判断近似相等。下面是实现这一功能的函数:
(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 的绝对值。