How can I test for primality?

前端 未结 16 2111
南方客
南方客 2020-12-05 08:29

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

相关标签:
16条回答
  • 2020-12-05 08:38

    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
    
    0 讨论(0)
  • 2020-12-05 08:39

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-05 08:40

    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.

    0 讨论(0)
  • 2020-12-05 08:42

    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;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-05 08:43

    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.

    0 讨论(0)
  • 2020-12-05 08:44

    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.

    0 讨论(0)
提交回复
热议问题