Primality Checking
May 1, 2009
Although the math looks difficult, the code is quite straight forward. Check?
calculates r and s in the outer loop, checks if a^{s} is 1 modulo n, and then the inner loop checks the other condition for each j from 0 to r1.
(define (check? a n)
(let loop ((r 0) (s ( n 1)))
(if (even? s) (loop (+ r 1) (/ s 2))
(if (= (expm a s n) 1) #t
(let loop ((j 0) (s s))
(cond ((= j r) #f)
((= (expm a s n) ( n 1)) #t)
(else (loop (+ j 1) (* s 2)))))))))
Then prime?
tests a few boundary conditions and performs fifty random calls to check?
.
(define (prime? n)
(cond ((< n 2) #f) ((= n 2) #t) ((even? n) #f)
(else (let loop ((k 50))
(cond ((zero? k) #t)
((not (check? (randint 1 n) n)) #f)
(else (loop ( k 1))))))))
Expm
(modular exponentiation) and randint
come from the Standard Prelude. A quick test shows that 2^{89}1 = 618970019642690137449562111 is prime:
> (prime? ( (expt 2 89) 1))
#t
You can run this code at http://codepad.org/rSDxFrZn.
[…] Praxis – Primality Checking By Remco Niemeijer Today’s Programming Praxis problem is about checking whether or not a number is prime. We’re supposed […]
My Haskell solution (see http://bonsaicode.wordpress.com/2009/05/01/programmingpraxisprimalitychecking/ for a version with comments):
import Control.Arrow
import Data.Bits
import Data.List
import System.Random
isPrime :: Integer > StdGen > Bool
isPrime n g =
let (s, d) = (length *** head) . span even $ iterate (flip div 2) (n – 1)
xs = map (expm n d) . take 50 $ randomRs (2, n – 2) g
in all (\x > elem x [1, n – 1] 
any (== n – 1) (take s $ iterate (expm n 2) x)) xs
expm :: Integer > Integer > Integer > Integer
expm m e b = foldl’ (\r (b’, _) > mod (r * b’) m) 1 .
filter (flip testBit 0 . snd) .
zip (iterate (flip mod m . (^ 2)) b) $
takeWhile (> 0) $ iterate (flip shiftR 1) e
main :: IO ()
main = print . isPrime (2 ^ 89 – 1) =<< getStdGen [/sourcecode]
I’m slowly working my way through old exercises now that I have some free time. Here’s
my attempt in Common Lisp; I’m trying to learn the language, even though I already had Pythoned MillerRabin previously.
Wow, so much code needed in OCaml to solve this exercise in a selfcontained fashion! First of all, a generalpurpose function to return a random
Big_int
between 0 and a specifiedmax
(exclusive):(You can’t go much lower level than this.) Next, some utility functions on
Big_int
s:Finally, an imperativestyle RabinMiller test:
Two optimizations were applied: first, the random a should be greater than 1; second, the successive powers of a in the inner loop are calculated inductively by (modular) squaring.
I made a mistake in
random_big_int
. Lines 10 and 11 are wrong, they should read:This is a Haskell program I wrote (ironically enough around May 2009, though I hadn’t heard about this website back then.) This was my first relatively nontrivial Haskell program.
To test 2^89 1 use,
.\millerrabin.exe t 618970019642690137449562111
Rewrote the Haskell MillerRabin in Clojure as my first Clojure program. It is linebyline translation, pretty much. Main difference is that one can’t generate random numbers > 2^63, so that is taken into account when generating tests.
{
{前几天最近这段时间这些天前段时间前些日子没多久前不久前}刚开始{碰啃练习接触学接触到学习} python，现在{碰到遇到遭遇到接触到要用到}验证码问题，{网上上网}{查了下google了一下百度了一下谷歌了一下baidu了一下百度了一会谷歌了一会google了一会搜了一下搜了一会}{相关}{内容知识资料教程}，{知道得知获悉了解到了解好像似乎}用python获取验证码{的人}还是{比较多的不少不在少数挺多的}。自己琢磨了{一番一下一下午一整天一早上一晚上整个上午整个下午整个晚上}，用的是{开源的免费的不用钱的不用银子的不用付费的}打码工具tesseractor，但{始终最后最终后来至今到现在到目前}都没{搞出来搞定成功获取验证码成功获取验证码获取到验证码弄出验证码解决验证码问题搞出验证码}，{不知道不清楚不了解不明白没弄懂没明白没了解没搞清没搞懂没搞明白}是什么{问题原因情况}，难道是{免费没好货免费的问题天下没有免费的午餐}？{有没有有无知不知知不知道有人知道有没人知道有没谁知道有谁知道有谁了解有谁用过}{什么哪个哪些哪一些哪个}付费的{推荐软件平台应用工具}吗？

{前几天最近这段时间这些天前段时间前些日子没多久前不久前}刚开始{碰啃练习接触学接触到学习}
python，现在{碰到遇到遭遇到接触到要用到}验证码问题，{通过测试了下弄了下搞了下}本地可以{解析获取弄搞读取读}出{一个}字符串，{然后但是可是接着不过}再提交{的时候后之后过后以后}这个验证码已经{变改变变化}了，{我}{在这里在这现在如今}想{问咨询询问了解搞明白弄懂}的是{如何怎样怎么}{才}能{保证保持}这两{者个}{一致相同不变}。