Common lisp 公共Lisp中分数的相等性检查
所以我知道Lisp做分数,这很好。但是为什么这个相等检查返回NIL:Common lisp 公共Lisp中分数的相等性检查,common-lisp,precision,floating-accuracy,fractions,Common Lisp,Precision,Floating Accuracy,Fractions,所以我知道Lisp做分数,这很好。但是为什么这个相等检查返回NIL: * (= 0.2 1/5) NIL …如果先将其转换为float,则返回True: * (= 0.2 (float 1/5)) T 我试过SBCL和CLISP 实现是否不完整,或者这种行为背后是否有特殊原因或逻辑 about=上写着: 如果所有数字的值相同,则=的值为真;否则,这是错误的 而onreal上显示: 类型rational和float是类型real的不相交子类型 换句话说,您可以比较它们,
* (= 0.2 1/5)
NIL
…如果先将其转换为float
,则返回True:
* (= 0.2 (float 1/5))
T
我试过SBCL
和CLISP
实现是否不完整,或者这种行为背后是否有特殊原因或逻辑 about=
上写着:
如果所有数字的值相同,则=
的值为真;否则,这是错误的
而onreal
上显示:
类型rational
和float
是类型real
的不相交子类型
换句话说,您可以比较它们,因为它们都是数字,但它们不同,因为子类型是不相交的,所以它们是不同的值
您可以将它们转换为相同的数字“子集”,float,然后比较将返回true
这种行为的原因是,
float
数字通常有一个近似的表示(见@coredump的注释和链接),而有理数有一个精确的表示,因此比较那些外部“看起来”相同但内部(二进制)不同的值是不明智的表示法。通用Lisp中的比率
请注意,分数(在公共Lisp中它本身不是数字类型)在Lisp中转换为有理数rational
、ratio
和integer
(以及其他)是公共Lisp中的实际数字类型。如果您输入一个分数,它将标准化为有理数(整数或比率数)
数值比较
比较浮动和比率时,将浮动值转换为有理值,然后进行精确比较。请参阅:
比率未转换为浮动,但浮动转换为有理数。
出现问题的原因是某些浮动未转换为您预期的比率。根本的问题是浮点数不一定有精确的表示。给出天真的预期结果时,不需要将非精确数转换为精确有理数
不幸的是,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
但是:
注意,类型
rational
组合了不相交的子类型ratio
和integer
。因此(rational 1.0)
可以是一个整数,而不是一个比率。浮点数的不精确性?另请参见,(=0.51/2)
返回T
。0.5在基2和基10端接:
CL-USER 14 > (= 0.2 (float 1/5))
T
CL-USER 15 > (= (rational 0.2) 1/5)
NIL