There are two problems with this.
Fermat's Little Theorem
If p is a prime and a is any integer not divisible by p, then a^(p - 1) - 1 is divisible by p.
That does not give you the converse: just because a^(p-1)-1 is divisible by p does not mean that p is prime. There is Fermat's primality test which involves trying this for many different values of a, which results in a high-confidence of its primality.
Floating Point
You're not going to be able to do this easily directly in Lua. Numbers in Lua do not store full integer precision. As small as 35, you have 3^35 == 3^35 - 1, which means you're not going to easily be able to apply this directly.
Thanks to properties of modular arithmetic, though, and fast-exponentiation-by-squaring, you can make this work in Lua.
First, the slow way to do exponentiation: repeated multiplication:
function exp(a, b)
local n = 1
for i = 1, b do
n = n * a
end
return n
end
We'll have the same problem as before. We need to use the fact that we are computing thing mod another number.
There is a nice property that (a * b) % n == (a % n) * (b % n). This means we can take % after each step, and avoid big numbers:
function exp(a, b, mod)
local n = 1
for i = 1, b do
n = n * a % mod
end
return n
end
This isn't very fast, though. We have to do 2000 multiplications to test b=2000. We can use fast exponentiation by squaring to improve this significantly.
The observation is that x ^ (2n) == (x ^ n) ^ 2. Thus we can turn 2n multiplications into 1 + n multiplications.
function fastexp(a, b)
if b == 0 then
return 1
elseif b % 2 == 0 then
return fastexp(a, b / 2) ^ 2
else
return a * fastexp(a, (b-1)/2) ^ 2
end
end
This is a log-time algorithm, thus b=2000 will take around 12 multiplications instead of 2000.
Of course, don't forget to add the mod in there:
function fastexp(a, b, mod)
if b == 0 then
return 1
elseif b % 2 == 0 then
return fastexp(a, b / 2, mod) ^ 2 % mod
else
return a * fastexp(a, (b-1)/2, mod) ^ 2 % mod
end
end
Fermat's Primality Test
function trial(a, p)
return fastexp(a, p-1, p) == 1
end
function isProbablyPrime(p, c)
for i = 1, c or 100 do
if not trial(math.random(2,p-1), p) then
return false
end
end
return true
end
for i = 1, 100 do
if isProbablyPrime(i) then
print(i)
end
end
There are other primality tests, too. I don't think Fermat's test is considered very good.
1 comment
If your trying generate a list of primes, I suggest a sieve such as https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes or https://en.wikipedia.org/wiki/Sieve_of_Sundaram