summaryrefslogtreecommitdiff
path: root/lisp/calculator.el
diff options
context:
space:
mode:
authorJay Belanger <jay.p.belanger@gmail.com>2007-07-04 04:20:35 +0000
committerJay Belanger <jay.p.belanger@gmail.com>2007-07-04 04:20:35 +0000
commitf50347a91b5dd8172c7975a3d1f85c6949d964dd (patch)
tree0f63be22c557fc1baa6311ffe2e842e1f2b4f4a6 /lisp/calculator.el
parentb71f9bdb2d58aa77ad9654cd7d1c95487b02acf0 (diff)
downloademacs-f50347a91b5dd8172c7975a3d1f85c6949d964dd.tar.gz
(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.
Diffstat (limited to 'lisp/calculator.el')
-rw-r--r--lisp/calculator.el45
1 files changed, 38 insertions, 7 deletions
diff --git a/lisp/calculator.el b/lisp/calculator.el
index 53a3c96d948..c1e0edb6276 100644
--- a/lisp/calculator.el
+++ b/lisp/calculator.el
@@ -278,7 +278,7 @@ Examples:
("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 @@ specified, then it is fixed, otherwise it depends on this variable).
`+' 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 @@ To use this, apply a binary operator (evaluate it), then call this."
(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."