有一个长整数m = 38941629971148227236N。我想生成1到1之间的数字e。 e< m,并检查e是否满足此要求:gcd(e,m)= 1。我的方法是使用(long(rand m))随机生成e,我收到了警告:
org.springframework.util.NumberUtils.convertNumberToTargetClass
我的代码是:
IllegalArgumentException Value out of range for long:
1.7166121075068025E19 clojure.lang.RT.longCast (RT.java:1254)
我知道结果超出范围很长,但我不知道有什么方法可以解决这个问题吗?
答案 0 :(得分:5)
问题在于(long (rand m))
,因为您选择的随机值通常远大于长度内的值。你想做一个bigint不长。这是一种解决方法:
(bigint (bigdec (rand 38941629971148227236N)))
请注意,以这种方式选择随机数实际上是产生一个double,它被转换为bigdec,转换为bigit。因此,可能的随机值的域是有限的。使用double作为基本随机数意味着不会生成所有可能的bigint。如果你想要真正的bigint随机选择,请看看this answer ...但如果你不太在意,只要你得到一个在适当范围内的bigint,这可能适合你:
(defn find-e [m]
(loop [e (bigint (bigdec (rand m)))]
(if (= 1 (gcd e m))
e
(recur (bigint (bigdec (rand m)))))))
答案 1 :(得分:4)
您可以使用the answer on generating random java.math.BigInteger
中的知识构建它,以获得更有效的解决方案:
(defn random-bigint [limit]
(let [bits (.bitLength limit)]
(loop [result (BigInteger. bits (ThreadLocalRandom/current))]
(if (< result limit)
(bigint result)
(recur (BigInteger. bits (ThreadLocalRandom/current)))))))
然后您的代码可以重用该函数:
(defn find-e [m]
(loop [e (random-bigint m)]
(if (= 1 (gcd e m))
e
(recur (random-bigint m)))))
这种生成随机数然后检查它是否在所需范围内的方法有一个缺点,即如果你非常不走运,你的循环将需要大量的迭代。您可以将其扩展为对重试次数进行限制,并在超出时将其失败。