如何使用rand-int生成可重复的随机序列

Mar*_*ars 9 clojure

我希望能够rand在Clojure中使用生成可重复的数字.(具体来说,我希望调用rand-nth或者Incanter的结果sample是可重复的,而这些调用rand-int反过来调用rand).

我从这个问题中发现,如果我使用clojure.data.generators,我可以重置随机状态:

(require '[clojure.data.generators :as gen])
(alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437)))
(gen/reservoir-sample 5 (range 1000)) ; => [940 591 636 12 755]
(gen/reservoir-sample 5 (range 1000)) ; => [376 540 827 307 463]
; reset random state:
(alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437)))
; now the same results are generated again:
(gen/reservoir-sample 5 (range 1000)) ; => [940 591 636 12 755]
(gen/reservoir-sample 5 (range 1000)) ; => [376 540 827 307 463]
Run Code Online (Sandbox Code Playgroud)

但是,该方法似乎只影响clojure.data.generators中的函数,这并不奇怪:

(alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437)))
(rand) ; => 0.9372552374760151
(rand) ; => 0.2712729314667742
; reset random state:
(alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437)))
; not same results as before:
(rand) ; => 0.630238593767316
(rand) ; => 0.426744420572015
Run Code Online (Sandbox Code Playgroud)

如何以可获得可重复结果的方式恢复随机状态rand?到目前为止,我还没有找到任何关于此的文档.

(另一个问题听起来似乎可能是同一个问题,但它要求的是完全不同的东西.)

Die*_*sch 4

可能不是最干净的方法,但你可以通过重新定义来使其工作clojure.core/rand

(ns clojure.core)

(def r (java.util.Random. 1))

(defn rand
  ([] (.nextDouble r))
  ([n] (.nextInt r n)))

(take 10 (repeatedly #(rand-int 10)))
Run Code Online (Sandbox Code Playgroud)

每次我运行它时都会产生 (5 8 7 3 4 4 4 6 8 8) 。

  • Clojure 的理念是不试图隐藏它在主机(在本例中为 JVM)上运行的事实。“下降到 Java”并不是一件坏事,特别是因为 Java 互操作非常容易。此外,Clojure 是一种相对年轻的语言。如果一个用例变得足够常见,有人会编写一个纯 Clojure 库来完成您的需要。我同意 Incanter 应该直接支持可重复性,并且我会提出一个问题。 (2认同)