我希望能够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?到目前为止,我还没有找到任何关于此的文档.
(另一个问题听起来似乎可能是同一个问题,但它要求的是完全不同的东西.)
可能不是最干净的方法,但你可以通过重新定义来使其工作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) 。