Соотношения в Common Lisp
Обратите внимание, что дробные числа (которые сами по себе не являются числовыми типами в Common Lisp) преобразуются в рациональные числа в Лиспе. rational
, ratio
и integer
(и другие) являются фактическими числовыми типами в Common Lisp. Если вы вводите дробь, она нормализуется до рационального числа (целого числа или отношения).
CL-USER 16 > 3/9
1/3
CL-USER 17 > 9/9
1
CL-USER 18 > 6/9
2/3
Числовое сравнение
Когда сравниваются число с плавающей запятой и отношение, значение с плавающей запятой преобразуется в рациональное, а затем выполняется точное сравнение. См.: CLHS, Rule of Float and Rational Contagion.
Отношение не преобразуется в число с плавающей запятой, но число с плавающей запятой преобразуется в рациональное.
Проблема возникает из-за того, что некоторые числа с плавающей запятой не преобразуются в ожидаемые соотношения. Основная проблема заключается в том, что числа с плавающей запятой не обязательно имеют точное представление. Преобразование неточного числа в точное рациональное не обязательно дает наивно ожидаемый результат.
К сожалению, преобразование 0.2
в рациональное число не обязательно 1/5
, но это:
CL-USER 7 > (rational 0.2)
13421773/67108864
Но 0.5
это 1/2
.
CL-USER 8 > (rational 0.5)
1/2
Вот что происходит в ваших примерах:
CL-USER 9 > (= 1/2 (rational 0.5))
T
CL-USER 10 > (= 1/5 (rational 0.2))
NIL
Так что это не
CL-USER 14 > (= 0.2 (float 1/5))
T
Но:
CL-USER 15 > (= (rational 0.2) 1/5)
NIL
Обратите внимание, что тип rational
объединяет непересекающиеся подтипы ratio
и integer
. Таким образом, (rational 1.0)
может быть целым числом, а не отношением.
person
Rainer Joswig
schedule
01.10.2015
(= 0.5 1/2)
возвращаетT
. 0.5 завершается как в базе 2, так и в 10: stackoverflow.com/a/1096929/124319 - person coredump   schedule 01.10.2015