Lisp интерактивный emacs, умноженный неправильно - PullRequest
0 голосов
/ 14 марта 2019

Я использую следующий код в Emacs Lisp Interaction:

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

, что дает мне 1114476179152563777. Тем не менее, ((1001^2)^2)^2 на самом деле 1008028056070056028008001. Как это возможно?

Ответы [ 2 ]

9 голосов
/ 14 марта 2019

@ Ответ Бармара точен для версий Emacs <27. </p>

В Emacs 27 была добавлена ​​поддержка bignum. NEWS говорит:

** Целые числа Emacs Lisp теперь могут иметь произвольный размер. Emacs использует библиотеку GNU Multiple Precision (GMP) для поддержки целые числа, размер которых слишком велик, чтобы поддерживать изначально. Целые числа изначально поддерживается как "fixnums", в то время как большие "bignums". Новые предикаты 'bignump' и 'fixnump' могут быть использованы для различать эти два типа целых чисел.

Вся арифметика, сравнение и логика (a.k.a. "побитовый") операции, в которых bignums имеют смысл, теперь поддерживают как fixnums, так и bignums. Однако обратите внимание, что в отличие от фикснумов, bignums не будут сравниваться равный 'eq', вы должны использовать вместо 'eql'. (Численное сравнение с '=', конечно, работает на обоих.)

Поскольку большие бигнумы занимают много памяти, Emacs ограничивает размер самая большая bignum, которую может создать программа на Лиспе. неотрицательное значение новой переменной 'integer-width' указывает максимальное количество битов, разрешенных в bignum. Emacs сигнализирует целое число ошибка переполнения, если этот предел превышен.

Несколько примитивных функций, ранее возвращавших значения с плавающей точкой или списки целые числа для представления целых чисел, которые не вписываются в фиксные числа. Эти функции теперь просто возвращают целые числа. Затронутые функции включают такие функции, как 'encode-char', которые вычисляют кодовые точки, функции как «атрибуты файла», которые вычисляют размеры файла и другие атрибуты, такие функции, как «идентификатор процесса», которые вычисляют идентификаторы процессов, и такие функции, как 'user-uid' и 'group-gid', которые вычисляют идентификаторы пользователей и групп.

и действительно использую мою версию 27.0.50:

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

(square (square (square 1001)))
1008028056070056028008001
9 голосов
/ 14 марта 2019

Emacs Lisp не реализует bignums, он использует целочисленный тип машины.Диапазон целых чисел, которые он поддерживает, находится между most-negative-fixnum и most-positive-fixnum.В 64-битной системе значение most-positive-fixnum будет равно 2 61 -1, которое имеет около 20 десятичных цифр.

См. Основы целочисленного типа в руководстве по Elisp.

Правильный результат вашего вычисления - 25 цифр, что намного больше этого.Расчет переполняется и оборачивается.Это должно быть правильно по модулю 2 62 .

Вместо этого вы можете использовать плавающую точку.У него гораздо больший диапазон, хотя очень большие числа теряют точность.

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