If I write this function in emacs-lisp:
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
=> factorial
It works well for small numbers like 5 or 10, but if I try and calculate (factorial 33) the answer is -1211487723752259584 which is obviously wrong, all large numbers break the function. In python this doesn't happen. What is causing this problem?
You can always invoke Emacs' calc
library when dealing with large numbers.
(defun factorial (n)
(string-to-number (factorial--1 n)))
(defun factorial--1 (n)
(if (<= n 1)
"1"
(calc-eval (format "%s * %s"
(number-to-string n)
(factorial--1 (- n 1))))))
ELISP> (factorial 33)
8.683317618811886e+036
Further reading:
(calc)
RET
(calc) Calling Calc from Your Programs
RET
Integers have a specific range. Values outside this range can't be represented. This is pretty standard across most -- but not all -- programming languages. You can find the largest number Emacs Lisp's integer datatype can handle on your computer by checking the value of most-positive-fixnum
.
Go to your *scratch*
buffer -- or any Lisp buffer -- and type in most-positive-fixnum
. Put the cursor at the end, then press C-x C-e
. On my computer, I get 2305843009213693951 as the value. Yours might differ: I'm on a 64 bit machine, and this number is about 2^61
. The solution to the factorial of 33 is 8683317618811886495518194401280000000. That's about 2^86, which is also more than my Emacs can handle. (I used Arc to calculate it exactly, because Arc can represent any size integer, subject to boring things like the amount of memory you have installed).
The most simple solution seems to be Paul's one:
(defun factorial (n) (calc-eval (format "%s!" n)))
ELISP> (factorial 33)
8683317618811886495518194401280000000
However, I tried for fun, by another Calc way, without using calc-eval
and string
.
Because much more complex Emacs Lisp programs with Calc can be done in this way.
Calc's defmath
and calcFunc-
functions are so powerful within Emacs Lisp.
(defmath myFact (n) (string-to-number (format-number (calcFunc-fact n))))
ELISP> (calcFunc-myFact 33)
8.683317618811886e+36
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With