我有一个简单的功能,可以将数字相加并将它们相乘。
(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-multiply
,x
参数现在是add
(4)的结果,y
参数是{{1}的结果}(2)和mult
参数相同(2)。
然后我怎么能重复这个过程100次,然后打印add和mult的最终值?
非常感谢任何帮助。感谢
答案 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
生成连续的应用程序。使用first
和drop
选择您想要的结果,例如
(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
处保持不变。这样做并不会节省太多,所以我选择留下问题的处方。