Mercurial > emacs
changeset 81696:c29faa83ba3a
(calculator-expt, calculator-integer-p): New functions.
(calculator-fact): Check to see if the factorial will be too large
before computing it.
(calculator-initial-operators): Use `calculator-expt' to compute "^".
(calculator-mode): Mention that results which are too large will return inf.
author | Jay Belanger <jay.p.belanger@gmail.com> |
---|---|
date | Wed, 04 Jul 2007 04:17:21 +0000 |
parents | 8f00c712c722 |
children | efedc1f1fb08 |
files | lisp/calculator.el |
diffstat | 1 files changed, 38 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/calculator.el Tue Jul 03 18:17:07 2007 +0000 +++ b/lisp/calculator.el Wed Jul 04 04:17:21 2007 +0000 @@ -278,7 +278,7 @@ ("IC" acos (D (acos X)) x 6) ("IT" atan (D (atan X)) x 6) ("Q" sqrt sqrt x 7) - ("^" ^ expt 2 7) + ("^" ^ calculator-expt 2 7) ("!" ! calculator-fact x 7) (";" 1/ (/ 1 X) 1 7) ("_" - - 1 8) @@ -596,7 +596,8 @@ `+' and `-' can be used as either binary operators or prefix unary operators. Numbers can be entered with exponential notation using `e', except when using a non-decimal radix mode for input (in this case `e' -will be the hexadecimal digit). +will be the hexadecimal digit). If the result of a calculation is too +large (out of range for Emacs), the value of \"inf\" is returned. Here are the editing keys: * `RET' `=' evaluate the current expression @@ -1779,13 +1780,43 @@ (car calculator-last-opXY) (nth 1 calculator-last-opXY) x)) x)) +(defun calculator-integer-p (x) + "Non-nil if X is equal to an integer." + (condition-case nil + (= x (ftruncate x)) + (error nil))) + +(defun calculator-expt (x y) + "Compute X^Y, dealing with errors appropriately." + (condition-case + nil + (expt x y) + (domain-error 0.0e+NaN) + (range-error + (if (> y 0) + (if (and + (< x 0) + (= y (truncate y)) + (oddp (truncate y))) + -1.0e+INF + 1.0e+INF) + 0.0)) + (error 0.0e+NaN))) + (defun calculator-fact (x) "Simple factorial of X." - (let ((r (if (<= x 10) 1 1.0))) - (while (> x 0) - (setq r (* r (truncate x))) - (setq x (1- x))) - (+ 0.0 r))) + (if (and (>= x 0) + (calculator-integer-p x)) + (if (= (calculator-expt (/ x 3.0) x) 1.0e+INF) + 1.0e+INF + (let ((r (if (<= x 10) 1 1.0))) + (while (> x 0) + (setq r (* r (truncate x))) + (setq x (1- x))) + (+ 0.0 r))) + (if (= x 1.0e+INF) + x + 0.0e+NaN))) (defun calculator-truncate (n) "Truncate N, return 0 in case of overflow."