Fermat's Little Theorem: If n is a prime number and a is any positive integer less than n, then a raised to the nth power is congruent to a modulo n.
There are a small set of special numbers that "fool" this test, these are the Carmichael numbers. Further details can be found here http://en.wikipedia.org/wiki/Carmichael_number
Carmichael numbers are extremely rare. There are only 255 Carmichael numbers below 100,000,000. The smallest few are 561, 1105, 1729, 2465, 2821, and 6601.
Because the Carmichael numbers are a special subset of the Fermat prime numbers that satisfy the same condition, they can be known as absolute Fermat pseudoprimes. The Fermat "primes" can be known as Fermat pseudoprimes. If we remove the absolute Fermat pseudoprimes from the Fermat Pseudoprimes then we end up with the absolute primes.
There are revised versions of this test that remove the false positive Carmichael numbers, such as the famous Miller-Rabin test (Miller 1976, Rabin 1980). This starts from an alternate form of Fermat's Little Theorem, which states that if n is a prime number and a is any positive integer less than n, then a raised to the (n - 1)st power is congruent to 1 modulo n.
For this Scala example, I'm only using the original Fermat's Little Theorem. Here is the Scala file, the main contains a number of test cases.
import java.util.Random;
object FermatsLittleTheorem {
def main(args : Array[String]) {
val attempts = 10; // the number of attempts, higher numbers give greater confidence in positive results.
var n = 17;
println("result1: n = " + n + ", res = " + fastPrime(n, attempts)) // should be true
n = 13
println("result2: n = " + n + ", res = " + fastPrime(n, attempts)) // should be true
n = 11
println("result3: n = " + n + ", res = " + fastPrime(n, attempts)) // should be true
n = 9
println("result4: n = " + n + ", res = " + fastPrime(n, attempts)) // should be false
}
def fastPrime(n : Int, times : Int) : Boolean = {
if (times == 0)
true
else
if (fermatTest(n)) fastPrime(n, times - 1) else false
}
def expmod(base : Int, exp : Int, m : Int) : Int = {
if (exp == 0)
1
else if (even(exp))
remainder(square(expmod(base, (exp / 2), m)), m)
else
remainder(base * expmod(base, exp - 1, m), m)
}
def square(n : Int) : Int = {
n * n
}
def even(n : Int) : Boolean = {
remainder(n, 2) == 0
}
def remainder(n : Int, d : Int) : Int = {
n % d
}
def fermatTest(n : Int) : Boolean = {
def tryIt(a : Int) : Boolean = {
val res = expmod(a, n, n)
println("res = " + res + ", a = " + a + ", n = " + n + ", a % n = " + a % n)
res == a % n
}
tryIt(random(n - 1) + 1) // get a random int between 1 and n
}
def random(n : Int) : Int = { // return a random value between 0 and n - 1
val random = new Random();
random.nextInt(n);
}
}
This was refactored from the following Scheme code, as an exercise in Scala:
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (square (expmod base (/ exp 2) m))
m))
(else
(remainder (* base (expmod base (- exp 1) m))
m))))
(define (even? n)
(= (remainder n 2) 0))
(define (fermat-test n)
(define (try-it a)
(= (expmod a n n) a))
(try-it (+ 1 (random (- n 1)))))
(define (fast-prime? n times)
(cond ((= times 0) true)
((fermat-test n) (fast-prime? n (- times 1)))
(else false)))
A note of the tail recursiveness of the function fastPrime:
Comment (summary) from PaulP from #scala:
"It's not tail recursive but only for one reason. It's neither final nor private. It just needs to be able to determine it won't be overridden. It'd be tailrec if in an object.
There has also been discussion of a @tailrec annotation so you could get a compiler warning if a tagged function wasn't compiled tailrec as you'd thought."
.
No comments:
Post a Comment