clojure中如何随机生成长数

clojure中如何随机生成长数,clojure,Clojure,有一个长整数m=38941629971148227236N。我想生成一个介于1

有一个长整数m=38941629971148227236N。我想生成一个介于1
IllegalArgumentException Value out of range for long:
1.7166121075068025E19  clojure.lang.RT.longCast (RT.java:1254) 
我的代码是:

(defn find-e [m]
(loop [e (long (rand m))]
    (if (= 1 (gcd e m)) e
        (recur (long (rand m))))))

我很长时间都知道结果超出范围,但我不知道有没有办法解决这个问题?

问题在于
(long(rand m))
,因为您选择的随机值通常比long中的值大得多。你想做一个不长的点。这里有一种解决方法:

(bigint (bigdec (rand 38941629971148227236N)))
请注意,以这种方式选择随机数实际上产生了一个double,该double被转换为bigdec,bigdec被转换为bigit。因此,可能的随机值的范围是有限的。使用double作为基本随机数意味着不会生成所有可能的bigint。如果你想要真正的bigint随机选择,看看。。。但是如果你不太在意,只要你得到一个合适范围的bigint,这可能对你有用:

(defn find-e [m]
  (loop [e (bigint (bigdec (rand m)))]
    (if (= 1 (gcd e m))
      e
      (recur (bigint (bigdec (rand m)))))))

您可以使用来自的知识构建它,以获得更高效的解决方案:

(defn random-bigint [limit]
  (let [bits (.bitLength limit)]
    (loop [result (BigInteger. bits (ThreadLocalRandom/current))]
      (if (< result limit)
        (bigint result)
        (recur (BigInteger. bits (ThreadLocalRandom/current)))))))

这种生成随机数然后检查其是否在所需范围内的方法有一个缺点,即如果非常不走运,循环将需要大量迭代。您可以将其扩展为对重试次数的限制,并在超过该限制时出现异常失败。

回答得非常好。对于较大的
限制
s,重试次数不应该是个问题。实际上我错了,这可能是个问题,因为每一位都会使搜索空间加倍。而
限制越大
就越糟糕。
(defn find-e [m]
  (loop [e (random-bigint m)]
    (if (= 1 (gcd e m))
      e
      (recur (random-bigint m)))))