【发布时间】:2016-02-07 04:27:29
【问题描述】:
使用 Clojure,我如何生成一个随机长数字?我知道 Clojure 有一个 rand-int 函数,但它只适用于整数。如果给定的数字很长,我会收到这个 repl 错误:
IllegalArgumentException Value out of range for int: 528029243649 clojure.lang.RT.intCast (RT.java:1205)
【问题讨论】:
标签: clojure
使用 Clojure,我如何生成一个随机长数字?我知道 Clojure 有一个 rand-int 函数,但它只适用于整数。如果给定的数字很长,我会收到这个 repl 错误:
IllegalArgumentException Value out of range for int: 528029243649 clojure.lang.RT.intCast (RT.java:1205)
【问题讨论】:
标签: clojure
如果你看一下rand-int的来源
(defn rand-int
"Returns a random integer between 0 (inclusive) and n (exclusive)."
[n] (int (rand n)))
你可以做类似的事情
(long (rand n)))
【讨论】:
Clojure 的 rand 和 rand-int 使用 java.util.Random 作为底层随机数生成器。如果您的应用程序严重依赖随机数,您可能需要考虑使用用 Java 编写的 higher-quality random number generator,例如 MersenneTwisterFast。这有一个nextLong() 方法,并且在 Clojure 中很容易使用。 Java 的标准类SecureRandom 也可能值得考虑;它的设计目的与 Mersenne Twister 不同。还有其他不错的 Java 随机数生成器可用。取决于您使用随机数的目的。对于偶尔使用随机数,java.util.Random 可能就可以了。其他人在 cmets 中提到了其他选项。
我将描述MersenneTwisterFast 的用法。使用我提到的其他类基本相同,但没有初始步骤。
使用 Leiningen,将类似这样的内容添加到 project.clj:
:java-source-paths ["src/java"]
然后将 MersenneTwisterFast.java 的 Java 源代码放在 src/java/ec/util 中。然后你可以这样做:
(ns my.namespace
(:import [ec.util MersenneTwisterFast]))
(def rng (MersenneTwisterFast. 42)) ; Specify a different seed, e.g. from system time.
(defn next-long [] (.nextLong rng))
【讨论】:
long。使用j.u.Random中的对应方法即可
ThreadLocalRandom,它的方法选择范围更广,不需要创建实例:(.nextLong (java.util.concurrent.ThreadLocalRandom/current) 528029243649)。
ThreadLocalRandom。 (由于我不熟悉它,我想我只会让您的评论成为信息来源,而不是不断地在我的答案中添加选项。不过,我会添加一个指向 cmets 的注释。)