【问题标题】:Clojure Koan Factorial Function ImplementationsClojure Koan 阶乘函数实现
【发布时间】:2015-11-09 22:27:46
【问题描述】:

我正在学习 clojure 并完成 clojure-koan 练习。其中一个练习是关于implementing a factorial function。我在玩耍时注意到:

我的递归实现似乎适用于大量数字:

(defn factorial-1 [n]
   (loop [n n f 1]
      (if (= n 1)
          f
          (recur (dec n) (* f n)))))

在 REPL 中调用 (factorial-1 1000N) 会产生一个数字:402387260077093773...

但是,当我尝试以下惰性序列方法时:

(defn factorial-2 [n]
   (reduce * 1 (range 1 (inc n))))

在 REPL 中调用 (factorial-2 1000N) 会产生错误:

ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)

为什么看似懒惰的序列方法会导致整数溢出错误?

【问题讨论】:

    标签: recursion clojure


    【解决方案1】:

    尽管通过了 1000N,但您实际上从未在乘法中使用任何大整数,因为您仅使用该数字来确定计算的结束。从1 开始乘法运算,然后乘以1,然后乘以2,以此类推。如果您修改 factorial-2 的定义以使用 bigint,您将获得预期的行为:

    (defn factorial-2 [n]
      (reduce * 1N (range 1 (inc n))))
    

    【讨论】:

    • 感谢您提供更多见解!我没有意识到 reduce 的初始值类型会改变行为。
    【解决方案2】:

    或者你可以简单地使用*'函数。

    (defn factorial-3 [n]
      (reduce *' (range 1 (inc n))))
    

    *' 函数支持任意精度。如果数字在Long 的范围内,它将返回Long。如果范围超出 Long 范围,则返回BigInt

    【讨论】:

    • 有趣。我不知道*' 函数。我假设 clojure.core 命名空间中存在这个函数,这被认为是更惯用的 clojure。
    猜你喜欢
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 2017-03-02
    • 2023-03-25
    • 1970-01-01
    • 2011-08-08
    相关资源
    最近更新 更多