3.4 Сравнение чисел

Для проверки числового равенства чисел обычно следует использовать = вместо нечисловых предикатов сравнения, таких как eq, eql и equal. Отдельные объекты с плавающей запятой и большие целые числа могут быть численно равны. Если вы используете eq для их сравнения, вы проверяете, являются ли они одним и тем же объектом; если вы используете eql или equal, вы проверяете, являются ли их значения неразличимыми. В отличие от этого, = использует числовое сравнение и иногда возвращает t, когда нечисловое сравнение вернуло бы nil, и наоборот. См. Основы чисел с плавающей запятой.

В Emacs Lisp, если два fixnum численно равны, они являются одним и тем же объектом Lisp. То есть, eq эквивалентен = для fixnum. Иногда удобно использовать eq для сравнения неизвестного значения с fixnum, потому что eq не выдает ошибку, если неизвестное значение не является числом — он принимает аргументы любого типа. В протиницу с этим, = сигнализирует об ошибке, если аргументы не являются числами или маркерами. Однако лучшей практикой программирования является использование =, даже для сравнения целых чисел.

Иногда полезно сравнивать числа с помощью eql или equal, которые считают два числа равными, если они имеют одинаковый тип данных (оба целые числа или оба числа с плавающей запятой) и одинаковое значение. В отличие от этого, = может считать целое число и число с плавающей запятой равными. См. Предикаты равенства.

Есть еще один нюанс: поскольку арифметика с плавающей запятой не является точной, часто плохой идеей является проверка равенства значений с плавающей запятой. Обычно лучше проверять приблизительное равенство. Вот функция для этого:

(defvar fuzz-factor 1.0e-6)
(defun approx-equal (x y)
  (or (= x y)
      (< (/ (abs (- x y))
            (max (abs x) (abs y)))
         fuzz-factor)))
Функция: = number-or-marker &rest number-or-markers

Эта функция проверяет, численно ли равны все ее аргументы, и возвращает t, если да, nil в противном случае.

Функция: eql value1 value2

Эта функция работает как 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, в то время как = делает обратное.

Функция: /= number-or-marker1 number-or-marker2

Эта функция проверяет, численно ли равны ее аргументы, и возвращает t, если они не равны, и nil, если равны.

Функция: < number-or-marker &rest number-or-markers

Эта функция проверяет, является ли каждый аргумент строго меньше следующего аргумента. Она возвращает t, если да, nil в противном случае.

Функция: <= number-or-marker &rest number-or-markers

Эта функция проверяет, является ли каждый аргумент меньше или равен следующему аргументу. Она возвращает t, если да, nil в противном случае.

Функция: > number-or-marker &rest number-or-markers

Эта функция проверяет, является ли каждый аргумент строго больше следующего аргумента. Она возвращает t, если да, nil в противном случае.

Функция: >= number-or-marker &rest number-or-markers

Эта функция проверяет, является ли каждый аргумент больше или равен следующему аргументу. Она возвращает t, если да, nil в противном случае.

Функция: max number-or-marker &rest numbers-or-markers

Эта функция возвращает наибольшее из своих аргументов.

(max 20)
     ⇒ 20
(max 1 2.5)
     ⇒ 2.5
(max 1 3 2.5)
     ⇒ 3
Функция: min number-or-marker &rest numbers-or-markers

Эта функция возвращает наименьшее из своих аргументов.

(min -4 1)
     ⇒ -4
Функция: abs number

Эта функция возвращает абсолютное значение number.