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)
我试过在SBCL和CLISP.
实施是否不完整或是否存在这种行为背后的特殊原因或逻辑?
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.5是1/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组合了不相交的子类型ratio和integer.因此(rational 1.0)可以是整数,而不是比率.