我试图通过defmulti和defmethod来计算阶乘。
(defmulti factorial identity)
(defmethod factorial 0 [_] 1)
(defmethod factorial :default [num]
(* num (factorial (dec num))))
适用于小数字
(-> 10 factorial) ;;3628800
(-> 2 factorial) ;; 2
它显示了因子40的整数溢出异常
(-> 40 factorial)
ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow
我的好奇心是
我们如何使用defmulti和defmethod计算大数的阶乘?
答案 0 :(得分:2)
Clojure的数字类型实现建立在主机平台的数字类型之上。定义任意大小标志N
时,Your solution有效,因为JVM上的基础数字类型发生了变化。
(type 10) ;=> java.lang.Long
(type 10N) ;=> clojure.lang.BigInt
clojure.lang.BigInt
uses either java.math.BigInteger
or a Java long
as the underlying type,具体取决于数字的位大小。
在另一台主机上,浏览器的Javascript引擎,这两种类型都是JavaScript的本机Number
。 factorial
函数在ClojureScript中的结果最多为170。溢出时不抛出,但返回JavaScript编号值Infinity:
(factorial 170) ; => 7.257415615307994e+306
(factorial 170N) ; => 7.257415615307994e+306
(factorial 171N) ; => Infinity
更新: This answer(由@cske指出)提供了一个使用*'
运算符的简洁解决方案,如果它运行数字类型突然增加会溢出:
(defmethod factorial :default [num]
(*' num (factorial (dec num))))
(factorial 40) ; => 815915283247897734345611269596115894272000000000N
答案 1 :(得分:0)
我已经解决了它
(-> 40N factorial) ;;815915283247897734345611269596115894272000000000N