使用Common Lisp中的分数进行等式检查

Suz*_*ana 5 precision common-lisp floating-accuracy fractions

所以我知道Lisp会做出很棒的分数.但是为什么这个相等检查会返回NIL:

* (= 0.2 1/5)          

NIL
Run Code Online (Sandbox Code Playgroud)

...如果它转换为float第一个则返回True :

* (= 0.2 (float 1/5))

T
Run Code Online (Sandbox Code Playgroud)

我试过在SBCLCLISP.

实施是否不完整或是否存在这种行为背后的特殊原因或逻辑?

Rai*_*wig 6

Common Lisp中的比率

请注意,分数(它本身不是Common Lisp中的数字类型)在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
Run Code Online (Sandbox Code Playgroud)

数字比较

比较浮点数和比率时,将浮点值转换为有理数,然后进行精确比较.请参阅:CLHS,Float规则和Rational Contagion.

该比率未转换为浮点数,但浮点数转换为有理数.

出现问题是因为某些浮动没有转换为您期望的比率.根本问题是浮点数不一定是精确表示.将非精确数转换为精确理数不是必要的,给出了天真的预期结果.

不幸的是,转换为0.2有理数不一定1/5,但是:

CL-USER 7 > (rational 0.2)
13421773/67108864
Run Code Online (Sandbox Code Playgroud)

不过0.51/2.

CL-USER 8 > (rational 0.5)
1/2
Run Code Online (Sandbox Code Playgroud)

这是您的示例中发生的情况:

CL-USER 9 > (= 1/2 (rational 0.5))
T

CL-USER 10 > (= 1/5 (rational 0.2))
NIL
Run Code Online (Sandbox Code Playgroud)

所以事实并非如此

CL-USER 14 > (= 0.2 (float 1/5))
T
Run Code Online (Sandbox Code Playgroud)

但:

CL-USER 15 > (= (rational 0.2) 1/5)
NIL
Run Code Online (Sandbox Code Playgroud)

请注意,该类型rational组合了不相交的子类型ratiointeger.因此(rational 1.0)可以是整数,而不是比率.