clojure:使用defmulti和defmethod计算数字的因子

时间:2017-07-19 04:39:08

标签: clojure

我试图通过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计算大数的阶乘?

2 个答案:

答案 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的本机Numberfactorial函数在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