How to create the most compact mapping n → isprime(n) up to a limit N?

后端 未结 30 2741
遇见更好的自我
遇见更好的自我 2020-11-22 02:11

Naturally, for bool isprime(number) there would be a data structure I could query.
I define the best algorithm, to be the algorithm that pr

30条回答
  •  逝去的感伤
    2020-11-22 02:44

    For large numbers you cannot simply naively check whether the candidate number N is divisible by none of the numbers less than sqrt(N). There are much more scalable tests available, such as the Miller-Rabin primality test. Below you have implementation in python:

    def is_prime(x):
        """Fast implementation fo Miller-Rabin primality test, guaranteed to be correct."""
        import math
        def get_sd(x):
            """Returns (s: int, d: int) for which x = d*2^s """
            if not x: return 0, 0
            s = 0
            while 1:
                if x % 2 == 0:
                    x /= 2
                    s += 1
                else:
                    return s, x
        if x <= 2:
            return x == 2
        # x - 1 = d*2^s
        s, d = get_sd(x - 1)
        if not s:
            return False  # divisible by 2!
        log2x = int(math.log(x) / math.log(2)) + 1
        # As long as Riemann hypothesis holds true, it is impossible
        # that all the numbers below this threshold are strong liars.
        # Hence the number is guaranteed to be a prime if no contradiction is found.
        threshold = min(x, 2*log2x*log2x+1)
        for a in range(2, threshold):
            # From Fermat's little theorem if x is a prime then a^(x-1) % x == 1
            # Hence the below must hold true if x is indeed a prime:
            if pow(a, d, x) != 1:
                for r in range(0, s):
                    if -pow(a, d*2**r, x) % x == 1:
                        break
                else:
                    # Contradicts Fermat's little theorem, hence not a prime.
                    return False
        # No contradiction found, hence x must be a prime.
        return True
    

    You can use it to find huge prime numbers:

    x = 10000000000000000000000000000000000000000000000000000000000000000000000000000
    for e in range(1000):
        if is_prime(x + e):
            print('%d is a prime!' % (x + e))
            break
    
    # 10000000000000000000000000000000000000000000000000000000000000000000000000133 is a prime!
    

    If you are testing random integers probably you want to first test whether the candidate number is divisible by any of the primes smaller than, say 1000, before you call Miller-Rabin. This will help you filter out obvious non-primes such as 10444344345.

提交回复
热议问题