Lisp交互式Emacs乘法不正确

时间:2019-03-14 01:28:59

标签: emacs numbers lisp elisp bignum

我正在Emacs Lisp交互上运行以下代码:

(defun square (x) (* x x))
(square (square (square 1001)))

这给了我1114476179152563777。但是,((1001^2)^2)^2实际上是1008028056070056028008001。 这怎么可能?

2 个答案:

答案 0 :(得分:9)

Emacs Lisp没有实现bignums,它使用了机器的整数类型。它支持的整数范围在most-negative-fixnummost-positive-fixnum之间。在64位系统上,most-positive-fixnum将是2 61 -1,大约有20个十进制数字。

请参见Elisp手册中的Integer Basics

您的计算正确结果是25位数字,比这大得多。计算溢出并回绕。应该是正确的2 62 模。

您可以改用浮点数。它的范围更大,尽管很多数字会降低精度。

(square (square (square 1001.0)))
1.008028056070056e+24

答案 1 :(得分:9)

@Barmar的答案对于<27的Emacs版本是正确的。

在Emacs中增加了27个bignum支持。新闻说:

  

** Emacs Lisp整数现在可以具有任意大小。   Emacs使用GNU Multiple Precision(GMP)库来支持   整数,其大小太大而无法本地支持。整数   本机支持的称为“ fixnums”,而较大的   “ bignums”。新的谓词“ bignump”和“ fixnump”可用于   区分这两种类型的整数。

     

所有算术,比较和逻辑(也称为“按位”)   bignum有意义的操作现在支持fixnum和   bignums。但是,请注意,与fixnums不同,bignums不会进行比较   等于“ eq”,则必须改用“ eql”。 (数值比较   当然,两者都可以使用'='。

     

由于大型bignum占用大量内存,因此Emacs限制了   Lisp程序可以创建的最大bignum。的   新变量'integer-width'的非负值指定   bignum中允许的最大位数。 Emacs表示一个整数   如果超出此限制,则会发生溢出错误。

     

以前有几个原始函数返回浮点数或列表   整数,表示不适合fixnums的整数。这些   函数现在仅返回整数。受影响的功能   包括诸如“ encode-char”之类的用于计算代码点的函数   例如计算文件大小和其他属性的“文件属性”,   像'process-id'这样的函数来计算进程ID,而像   计算用户和组ID的“ user-uid”和“ group-gid”。

并确实使用我的27.0.50版本:

(defun square (x) (* x x))
square

(square (square (square 1001)))
1008028056070056028008001