【问题标题】:Why is my Miller Rabin algorithm not working (Haskell)?为什么我的米勒拉宾算法不起作用(Haskell)?
【发布时间】:2014-11-14 21:55:35
【问题描述】:

我在 Haskell 中实现了 Miller Rabin 测试。我试图严格遵循米勒拉宾测试的维基百科条目中给出的伪代码。现在我在网上发现,对于某些证人的选择,测试在一定的给定范围内是确定性的。我对 2^64 以下的素数感兴趣,所以我在这篇文章中找到了足够的界限 What witnesses do i need for Rabin-Miller test for numbers up to 10¹⁸?。但是,该代码似乎适用于我测试过的大多数小质数,但对于一些较大的质数却失败了。例如,我尝试了十位素数 5915587277,测试返回 false。我认为我的实现是正确的,但希望有人能发现我在哪里犯了错误并误解了关于 MR 测试的一些内容。提前感谢您的帮助。另外,对于看起来凌乱的代码感到抱歉。

isPrime :: Int -> Bool
isPrime n = millerRabinTest n (factorizeN (n-1))

{- factorizeN finds a number s and odd number d such that n -1 = (2^s)d by 
succesively dividing n by two if it is even. -}
factorizeN :: Int -> (Int, Int)
factorizeN n = fN n 0
  where
    fN n s | even n    = fN (n `div` 2) (s + 1)
           | otherwise = (n,s)

{- this is the main function. it takes w values from a set of witnesses
and checks if n passes the test. If it doesn't, n is not prime, if it does 
for all w, it is probably prime. -}
millerRabinTest :: Int -> (Int,Int) -> Bool
millerRabinTest n (d,s) = and [test n (expmod w d n) s | w <- onesToCheck]

{- this is the test that is used in the millerRabinTest function. it sees if
w^d = 1 mod n  or n-1 mod n, if not it multiplies by two
and checks again for a total of s-1 times. If it is never true then the number 
is not prime -}
test :: Int -> Int -> Int -> Bool
test n w s | w `elem` [1,n-1] = True
           | otherwise        = or [ (expmod w (2^k) n) `elem` [1,n-1]| k <- [1..s]]   

{- set of witnesses that should make the Miller Rabin test deterministic if
n < 2^64. -}
onesToCheck :: [Int]
onesToCheck = [2,325,9375,28178,450775,9780504,1795265022]

{- function that calculates a^e mod n. -}
expmod :: Int -> Int -> Int -> Int
expmod a e n  | e == 1           = a `mod` n
              | (e `mod` 2) == 0 = (expmod ((a*a) `mod` n) (e `div` 2) n)
              | otherwise        = (a*(expmod ((a*a) `mod` n) (e `div` 2) n)) `mod` n

【问题讨论】:

    标签: algorithm haskell primes primality-test


    【解决方案1】:

    当您计算a*a 时,您的Int 可能会在expmod 中溢出。 Int 是机器大小的整数,不超过 64 位。您应该将程序中出现的一些 Int 替换为任意精度整数类型 Integer

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 2011-04-13
      • 2014-07-28
      • 2011-12-02
      • 2017-04-24
      • 1970-01-01
      相关资源
      最近更新 更多