【问题标题】:why is my primality test failing so often when randomizing a BigInteger?为什么在随机化 BigInteger 时我的素数测试经常失败?
【发布时间】:2020-08-12 15:53:16
【问题描述】:

我无法对 p 和 q 都为真,大多数结果都是假的,或者很少 p 为真但 q 为假,为什么这个测试对 p 和 q 都不是真的?

BigInteger bitSize100 = new BigInteger("1").setBit(99);

for(int i = 0; i < 20; i++) {
        BigDecimal randomizer = new BigDecimal(Math.random()).multiply(new BigDecimal(bitSize100)); // get random 99 bit number
        BigInteger q = randomizer.toBigInteger().setBit(99); // must be 100 bits
        BigInteger p = q.add(q).add(BigInteger.ONE);
         System.out.println(p.isProbablePrime(100) + " " + q.isProbablePrime(100));
         
     }


output:
false false
false false
false false
false false
true false
false false
false false
false false
false false
false false
false false
false false
false false
false false
false false
false false
false false
false false
false false
false false

【问题讨论】:

  • 看起来你得到质数的概率很低。另外,您在测试的两个数字之间存在这种奇怪的数学关系。
  • 即使你正确地生成了它们,Prime Number Theorem 表示质数的渐近密度随着质数变大而变小。因此,对于较大的 n 值,人们会期望它们发生的频率较低。

标签: java biginteger bigdecimal


【解决方案1】:

首先BigDecimal randomizer = new BigDecimal(Math.random()).multiply(new BigDecimal(bitSize100)) 会导致 100 位随机性。

Math.random 返回一个 64 位大的 double 值,因此这是它可以创建的最大随机数(并且由于该值限制在 0 和 1 之间的值,实际随机数甚至更小) .

您应该使用Random.nextBytes() to fill a byte[] 与随机数据和the BigInteger constructor that takes such a byte[] 的组合来构建您的BigInteger。在这里完全避免使用 doubleBigDecimal 值。

编辑:事实上这正是you've been told on this other question of yours 4 hours ago

第二:大多数数字根本不是素数。如果你随机选择数字(甚至不排除偶数),那么它们中的绝大多数都不是素数。

我不知道Sophie Germain primes 是素数的几分之一,但显然不是全部。

因此,您的代码需要多次尝试(平均肯定超过 20 次)才能找到这样的素数对。

【讨论】:

  • n 位的随机整数有大约 1/n 的机会是素数(在一个小的常数因子内)。据我所知,如果 p 是素数,则 2*p + 1 也是如此。因此,随机 n 位整数是 Sophie Germain 素数的概率应该约为 1/(n^2 + n)。另一种说法:寻找 n 位素数的预期尝试次数是 O(n)。寻找 n 位 SG 素数的预期尝试次数为 O(n^2)。
猜你喜欢
  • 1970-01-01
  • 2020-03-13
  • 2016-01-31
  • 2021-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多