I am writing a little library with some prime number related methods. As I\'ve done the groundwork (aka working methods) and now I\'m looking for some optimization. Ofcours
This works very fast for testing primes (vb.net)
Dim rnd As New Random()
Const one = 1UL
Function IsPrime(ByVal n As ULong) As Boolean
If n Mod 3 = 0 OrElse n Mod 5 = 0 OrElse n Mod 7 = 0 OrElse n Mod 11 = 0 OrElse n Mod 13 = 0 OrElse n Mod 17 = 0 OrElse n Mod 19 = 0 OrElse n Mod 23 = 0 Then
return false
End If
Dim s = n - one
While s Mod 2 = 0
s >>= one
End While
For i = 0 To 10 - 1
Dim a = CULng(rnd.NextDouble * n + 1)
Dim temp = s
Dim m = Numerics.BigInteger.ModPow(a, s, n)
While temp <> n - one AndAlso m <> one AndAlso m <> n - one
m = (m * m) Mod n
temp = temp * 2UL
End While
If m <> n - one AndAlso temp Mod 2 = 0 Then
Return False
End If
Next i
Return True
End Function
Sadly, I haven't tried the algorithmic approaches before. But if you want to implement your approach efficiently, I'd suggest doing some caching. Create an array to store all prime numbers less than a defined threshold, fill this array, and search within/using it.
In the following example, finding whether a number is prime is O(1) in the best case (namely, when the number is less than or equal to maxPrime
, which is 821,461 for a 64K buffer), and is somewhat optimized for other cases (by checking mod over only 64K numbers out of the first 820,000 -- about 8%).
(Note: Don't take this answer as the "optimal" approach. It's more of an example on how to optimize your implementation.)
public static class PrimeChecker
{
private const int BufferSize = 64 * 1024; // 64K * sizeof(int) == 256 KB
private static int[] primes;
public static int MaxPrime { get; private set; }
public static bool IsPrime(int value)
{
if (value <= MaxPrime)
{
return Array.BinarySearch(primes, value) >= 0;
}
else
{
return IsPrime(value, primes.Length) && IsLargerPrime(value);
}
}
static PrimeChecker()
{
primes = new int[BufferSize];
primes[0] = 2;
for (int i = 1, x = 3; i < primes.Length; x += 2)
{
if (IsPrime(x, i))
primes[i++] = x;
}
MaxPrime = primes[primes.Length - 1];
}
private static bool IsPrime(int value, int primesLength)
{
for (int i = 0; i < primesLength; ++i)
{
if (value % primes[i] == 0)
return false;
}
return true;
}
private static bool IsLargerPrime(int value)
{
int max = (int)Math.Sqrt(value);
for (int i = MaxPrime + 2; i <= max; i += 2)
{
if (value % i == 0)
return false;
}
return true;
}
}
Try the sieve of eratosthenes -- that should take out getting the root and floating point issues.
As for the floor
, you will be better served by taking the ceiling
.
First and foremost, primes start from 2. 2 and 3 are primes. Prime should not be dividable by 2 or 3. The rest of the primes are in the form of 6k-1 and 6k+1. Note that you should check the numbers up to SQRT(input). This approach is very efficient. I hope it helps.
public class Prime {
public static void main(String[] args) {
System.out.format("%d is prime: %s.\n", 199, isPrime(199)); // Prime
System.out.format("%d is prime: %s.\n", 198, isPrime(198)); // Not prime
System.out.format("%d is prime: %s.\n", 104729, isPrime(104729)); // Prime
System.out.format("%d is prime: %s.\n", 104727, isPrime(982443529)); // Prime
}
/**
* Tells if a number is prime or not.
*
* @param input the input
* @return If the input is prime or not
*/
private boolean isPrime(long input) {
if (input <= 1) return false; // Primes start from 2
if (input <= 3) return true; // 2 and 3 are primes
if (input % 2 == 0 || input % 3 == 0) return false; // Not prime if dividable by 2 or 3
// The rest of the primes are in the shape of 6k-1 and 6k+1
for (long i = 5; i <= Math.sqrt(input); i += 6) if (input % i == 0 || input % (i + 2) == 0) return false;
return true;
}
}
I don't know if this is quite what you are looking for but if you are really concerned about speed then you should look into probablistic methods for testing primality rather than using a sieve. Rabin-Miller is a probabilistic primality test used by Mathematica.
I thought Prime numbers and primality testing was useful and the AKS algorithm sounds interesting even if it isn't particularly practical compared to a probabily based tests.