Clojure - 使用结果作为参数反复调用函数

时间:2017-04-28 09:30:06

标签: clojure

我有一个简单的功能,可以将数字相加并将它们相乘。

(defn add-and-multiply [x y z]
  (let [add (+ x y z) 
        mult (* x y z)] 
    (println "Add: " add) 
    (println "Mult: " mult)))

(add-and-multiply 1 1 2)
Add:  4
Mult:  2
nil

我如何再次调用add-and-multiplyx参数现在是add(4)的结果,y参数是{{1}的结果}(2)和mult参数相同(2)。

然后我怎么能重复这个过程100次,然后打印add和mult的最终值?

非常感谢任何帮助。感谢

4 个答案:

答案 0 :(得分:3)

我发现100次迭代后的结果太大而无法放入RAM中,我不会感到惊讶。除非我误解公式,否则这很像计算x*(x^2)*(x^4)*(x^8) ......最多x^(2^100),这简化为x^(2^200)。它实际上更大,因为还有一个添加步骤,但我认为与迭代乘法相比,它相对较小。 2 ^ 200已经很大了,但如果你需要,你可以计算它。

然而,2 ^(2 ^ 200)非常庞大。显然,你需要2 ^ 200位的RAM,至少要保持这个数字而不会损失精度。典型的台式计算机可能有16GB的RAM,即2 ^ 30(十亿)* 16演出* 8位/字节= 2 ^ 37位存储。您不仅需要一台台式计算机来存储它,而且还需要2 ^ 163台计算机。同样,我不能强调一个数字有多大。如果这个星球上的每一粒沙子都是一台装有16GB RAM的台式电脑,你就不会存储这个数字了。

所以,我会说你应该想出一个不同的方法来解决你真正的问题,假设你买不起整个星系的计算能力。

也就是说,关于如何将(f (f (f (f x))))概括为对f的任意数量的调用的机制,其他答案已经为您提供了如何使用iterate的良好解释,如果您选择运行时更易于管理的f,那么您将会很好。

答案 1 :(得分:2)

如果您更改add-and-multiply以返回两个结果:

(defn add-and-multiply [x y z]
  (let [add (+ x y z) 
        mult (* x y z)] 
    [add mult]))

然后您可以使用iterate生成连续的应用程序。使用firstdrop选择您想要的结果,例如

(first (drop 10 (iterate (fn [[x y]] (add-and-multiply x y 2)) [(bigint 1) (bigint 2)])))

答案 2 :(得分:1)

;; have a look at juxt
((juxt + * (fn [_ _ x] x)) 1 1 2) [4 2 2]

;; you can then use it like this:
(second (iterate (fn [v]
                   (apply (juxt + * (fn [_ _ x] x)) v)) [1 1 2])) ;; [4 2 2]

;; however it overflows quickly, so use +' *'
;; also, put it into a function
(defn add-and-multiply [times nb]
  (nth (iterate (fn [v]
                  (apply (juxt +' *' (fn [_ _ x] x)) v)) nb) times))

(add-and-multiply 10 [1 1 2]) ;; [7983075120467448500799760620188561621081118348584N 20456985749705433596250191236583540578087736309004220218432871989995224183078912N 2]

答案 3 :(得分:1)

这样做的简洁方法是

(defn compute [n]
  (let [step (fn [[x y z :as all]] [(reduce +' all) (reduce *' all) z])]
    (nth (iterate step [1 1 2]) n)))

我的笔记本电脑大约n = 35处的电量耗尽。

说明计算有点帮助:

(defn compute [n]
  (loop [x 1, y 1, z 2, n n]
    (if (zero? n)
      [x y z]
      (recur (+' x y z) (*' x y z) z (dec n)))))

但是生命太短暂,无法等待其中任何一个来计算n = 100的结果。

我们可以将z从计算中拉出来,因为它在2处保持不变。这样做并不会节省太多,所以我选择留下问题的处方。