我在Emacs Lisp Interaction上运行以下代码:
(defun square (x) (* x x))
(square (square (square 1001)))
这给了我1114476179152563777
。然而,((1001^2)^2)^2
实际上是1008028056070056028008001
。这怎么可能?
Emacs Lisp没有实现bignums,它使用机器的整数类型。它支持的整数范围是most-negative-fixnum
和most-positive-fixnum
之间。在64位系统上,most-positive-fixnum
将是261-1,其大约有20个十进制数字。
请参阅Elisp手册中的Integer Basics。
计算的正确结果是25位数,比这大得多。计算溢出并包裹。它应该是正确的模262。
您可以使用浮点代替。虽然非常大的数字会失去精确度,但它的范围要大得多。
(square (square (square 1001.0)))
1.008028056070056e+24
@ Barmar的回答对于Emacs版本<27来说是准确的。
在Emacs 27中增加了bignum支持。新闻说:
** Emacs Lisp整数现在可以是任意大小。 Emacs使用GNU Multiple Precision(GMP)库来支持大小太大而无法原生支持的整数。本机支持的整数称为“fixnums”,而较大的整数称为“bignums”。新谓词'bignump'和'fixnump'可用于区分这两种类型的整数。
bignums有意义的所有算术,比较和逻辑(a.k.a。“按位”)操作现在都支持fixnums和bignums。但请注意,与fixnums不同,bignums不会与'eq'进行比较,您必须使用'eql'。 (当然,与'='的数值比较对两者都有效。)
由于大型bignums消耗大量内存,因此Emacs限制了允许Lisp程序创建的最大bignum的大小。新变量“integer-width”的非负值指定了bignum中允许的最大位数。如果超出此限制,Emacs会发出整数溢出错误信号。
以前的几个原始函数返回浮点数或整数列表来表示不适合fixnums的整数。这些函数现在只返回整数。受影响的函数包括计算代码点的'encode-char',计算文件大小和其他属性的'文件属性'等函数,计算进程ID的'process-id'等函数,以及'user-uid等函数'和'group-gid'计算用户和组ID。
并确实使用我的27.0.50版本:
(defun square (x) (* x x))
square
(square (square (square 1001)))
1008028056070056028008001