【问题标题】:Why do these two methods of sampling primes run equally long?为什么这两种采样素数的方法运行时间相同?
【发布时间】:2017-09-23 08:17:59
【问题描述】:

所以我实现了自己的小型 RSA 算法,并在此过程中编写了一个函数来查找大素数。
首先,我编写了一个测试素数的函数prime?,然后我编写了两个版本的素数搜索函数。在第一个版本中,我只是测试随机 BigIntegers,直到我遇到一个素数。在第二个版本中,我对一个随机 BigInteger 进行采样,然后将其递增,直到找到一个素数。

(defn resampling []
  (let [rnd (Random.)]
    (->> (repeatedly #(BigInteger. 512 rnd))
         (take-while (comp not prime?))
         (count))))

(defn incrementing []
  (->> (BigInteger. 512 (Random.))
       (iterate inc)
       (take-while (comp not prime?))
       (count)))

(let [n 100]
  {:resampling   (/ (reduce + (repeatedly n resampling)) n)
   :incrementing (/ (reduce + (repeatedly n incrementing)) n)})

运行此代码会产生两个平均值:重采样函数为 332.41,递增函数为 310.74。
现在第一个数字对我来说完全有意义。 prime number theorem 表示n'th 素数的大小约为n*ln(n)(其中ln 是自然对数)。所以相邻素数之间的距离约为n*ln(n) - (n-1)*ln(n-1) ≈ (n - (n - 1))*ln(n) = ln(n)(对于n 的大值ln(n) ≈ ln(n - 1))。由于我正在采样 512 位整数,因此我希望素数之间的距离在 ln(2^512) = 354.89 附近。因此,随机抽样在达到素数之前平均需要大约 354.89 次尝试,结果非常好。
我的困惑是为什么递增函数要采取同样多的步骤。如果我想象在素数相距 355 个单位的网格上投掷飞镖,则平均只需大约一半的步数即可走到下一个更高的素数,因为平均而言,我会在两个素数之间击中中心。

prime?的代码有点长,大家可以看一下here。)

【问题讨论】:

  • 也许是因为你用增量方法测试的数字有一半是偶数?
  • @rossum 与 resampling 方法相同,所以我认为这不是原因
  • 检查它我得到了一个相似的号码。我的数学很生疏,从一开始就没有那么好,但据我所知,素数的分布是en.wikipedia.org/wiki/Poisson_distribution,这意味着这些数字从这里是有意义的:phillipmfeldman.org/mathematics/primes.html“任何两个独立泊松的总和随机变量产生另一个泊松随机变量。”这个问题可能更适合cs或数学网站之一。

标签: java random clojure primes


【解决方案1】:

您假设素数是均匀分布的,但事实并非如此。

让我们考虑以下可能的情况:如果素数总是成对出现,例如 10...0110...03,那么下一对将出现在 2*ln(n)。对于采样算法,这种分布没有区别,但对于递增算法,在这样一个对内开始的概率几乎为 0,因此这意味着它需要平均走大距离的一半,即ln(n) .

简而言之:要正确估计增量算法的行为,仅知道素数之间的平均距离是不够的。

【讨论】:

  • 当然!当我醒来时,我才意识到同样的错误。因此,如果我将素数理想化为与λ = 1/355 的泊松分布,那么当我进行初始样本时,直到下一个素数的等待时间将与相同的λ 呈指数分布。并且指数分布的随机变量的期望值为1/λ = 355。我应该早点看到这种方式的。
  • @SebastianOberhoff 很好的解释,比我挥手的论点干净得多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 2010-12-28
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多