157

Naturally, for bool isprime(number) there would be a data structure I could query.
I define the best algorithm, to be the algorithm that produces a data structure with lowest memory consumption for the range (1, N], where N is a constant.
Just an example of what I am looking for: I could represent every odd number with one bit e.g. for the given range of numbers (1, 10], starts at 3: 1110

The following dictionary can be squeezed more, right? I could eliminate multiples of five with some work, but numbers that end with 1, 3, 7 or 9 must be there in the array of bits.

How do I solve the problem?

Emma
  • 1
  • 9
  • 28
  • 53
AraK
  • 87,541
  • 35
  • 171
  • 230
  • 3
    Your request is a little vague. You give a signature that tests a single number but then ask for a data structure of (1,N]. Do you want an algorithm that generates a dictionary or just a one-shot function that checks if a single number is prime? – Michael Haren Nov 26 '09 at 03:35
  • @Michael Sorry, that is the best description I could comeup with. What I am looking is excactly as you are saying: a boolean dictionary. I would like to minimize the space of the dictionary. Thanks :) – AraK Nov 26 '09 at 03:37
  • 1
    If that's what you're looking for it's been asked already: http://stackoverflow.com/questions/1032427/efficient-storage-of-prime-numbers – Ben S Nov 26 '09 at 03:40
  • 15
    You would need to Ask the NSA – Charles Bretana Nov 26 '09 at 03:48
  • related: [Miller–Rabin primality test in Python](https://rosettacode.org/wiki/Miller%E2%80%93Rabin_primality_test#Python) – jfs Apr 26 '16 at 07:45
  • ([Characteristic function of primes: 1 if n is prime else 0](http://oeis.org/A010051)) – greybeard Jul 28 '19 at 02:08

32 Answers32

216

The fastest algorithm for general prime testing is AKS. The Wikipedia article describes it at lengths and links to the original paper.

If you want to find big numbers, look into primes that have special forms like Mersenne primes.

The algorithm I usually implement (easy to understand and code) is as follows (in Python):

def isprime(n):
    """Returns True if n is prime."""
    if n == 2:
        return True
    if n == 3:
        return True
    if n % 2 == 0:
        return False
    if n % 3 == 0:
        return False

    i = 5
    w = 2

    while i * i <= n:
        if n % i == 0:
            return False

        i += w
        w = 6 - w

    return True

It's a variant of the classic O(sqrt(N)) algorithm. It uses the fact that a prime (except 2 and 3) is of form 6k - 1 or 6k + 1 and looks only at divisors of this form.

Sometimes, If I really want speed and the range is limited, I implement a pseudo-prime test based on Fermat's little theorem. If I really want more speed (i.e. avoid O(sqrt(N)) algorithm altogether), I precompute the false positives (see Carmichael numbers) and do a binary search. This is by far the fastest test I've ever implemented, the only drawback is that the range is limited.

Mark Dickinson
  • 24,977
  • 7
  • 71
  • 104
Alexandru
  • 22,519
  • 17
  • 61
  • 78
  • 3
    Strictly speaking Carmicheals are not sufficient. Your pseudo-prime test must also not inadvertently miss the right base required to disprove FLT. The strong pseudo-prime algorithm is superior in that there are no "Carmicheals" with respect to it, but you still cannot be sure unless you have checked at least one quarter of the range. If you are not range limited, then it would seem to me that using SPP + something like pollard rho to classify the vast majority of numbers of a first pass before using something more heavy duty is the right approach. – Paul Hsieh Nov 26 '09 at 04:46
  • @Paul Hsieh: modified the wording, do you find this better now? – Alexandru Nov 26 '09 at 12:52
  • 7
    Two questions: Can you explain better what the variables `i` and `w` are, and what is meant by the form `6k-1` and `6k+1`? Thank you for your insight and the code sample (which I'm trying to understand) – Freedom_Ben Aug 08 '14 at 04:08
  • 6
    @Freedom_Ben Here you go, http://www.quora.com/Is-every-prime-number-other-than-2-and-3-of-the-form-6k±1 – Alan Dong Jan 17 '15 at 21:57
  • 7
    Wouldn't it be better to calculate the `sqrt` of `n` once and comparing `i` to it, rather than calculating `i * i` every cycle of the loop? – pedros May 18 '15 at 19:37
  • 3
    Actually AKS is NOT the fastest implementation. – Dschoni Sep 14 '15 at 12:39
  • 3
    @Dschoni ... but you can't fit the fastest implementation in the comment fields here to share with us? – GreenAsJade Feb 14 '16 at 03:22
  • @GreenAsJade: Well the question as it is posed is ambigious when it comes to primality checks. The accepted answer holds this with saying that you have to decide between a probabilistic and deterministic approach, the former being a lot faster. – Dschoni Feb 15 '16 at 08:50
  • 1
    When it comes to deterministic tests, ECPP (most likely in the Goldwasser implementation) should be faster than AKS. – Dschoni Feb 15 '16 at 09:02
  • Very fast solution! Thank you! – PanGalactic Apr 09 '16 at 17:28
  • 1
    Check it with `n = int(subprocess.check_output('openssl prime -generate -bits 2048 -hex'.split()), 16)` :P – Nick T Apr 20 '16 at 19:15
  • Im no expert here, but I do believe if you check for divisibility by the base before running a Fermat prime probability test, you circumvent the trouble Carmichaels give you. Ex. 561 is Carmichael, but if you divide by 3 before testing a base 3 Fermat test, you find it divides perfectly and is clearly composite. I dont even understand why people stumble with Carmichaels on these tests. Testing for divisibility by each base I use is always my first step. Youre supposed to do this anyway since the base is supposed to be coprime. – CogitoErgoCogitoSum Jul 23 '17 at 19:18
  • `isprime(1) True` - `if n <= 3: return 2 <= n` – greybeard Feb 25 '18 at 08:02
  • Is this approximate, or can I rely on this to generate lists of primes in a given range? It's definitely waaay faster than everything I tried now. My initial (read: dumb) method took 1:17 to check that 100000007 is prime, my second method took half of that, 37 seconds, and this...took about 0.3 seconds! :O – Daniel Springer Jul 19 '18 at 20:38
  • 4
    It fails for number 1 :( – Damjan Pavlica Aug 22 '18 at 10:53
81

There are many ways to do the primality test.

There isn't really a data structure for you to query. If you have lots of numbers to test, you should probably run a probabilistic test since those are faster, and then follow it up with a deterministic test to make sure the number is prime.

You should know that the math behind the fastest algorithms is not for the faint of heart.

Ben S
  • 65,441
  • 30
  • 165
  • 210
26

The best method, in my opinion, is to use what's gone before.

There are lists of the first N primes on the internet with N stretching up to at least fifty million. Download the files and use them, it's likely to be much faster than any other method you'll come up with.

If you want an actual algorithm for making your own primes, Wikipedia has all sorts of good stuff on primes here, including links to the various methods for doing it, and prime testing here, both probability-based and fast-deterministic methods.

There should be a concerted effort to find the first billion (or even more) primes and get them published on the net somewhere so people can stop doing this same job over and over and over and ... :-)

paxdiablo
  • 772,407
  • 210
  • 1,477
  • 1,841
  • 2
    @hamedbh: Interesting. Have you tried to download those files? It appears they don't exist. – paxdiablo Dec 07 '16 at 00:47
  • Not yet, I'm afraid: I was just looking quickly during my lunch break. I'll delete that link in case there's anything malicious about it. So sorry, I really should have checked it first. – Hamed Dec 07 '16 at 04:55
  • this sounds very interesting....would not it be fine if we store them in long long int array... – Aadhil RF Apr 28 '17 at 10:15
  • 1
    Such lists **do** exist. Ive seen them years ago but never cared to download them. The truth is, they take up a lot of space (relatively speaking), and shouldn't be included in programs one sells or distributes. Furthermore, they will always and forever be incomplete. It kind of does make more sense to test each number that comes up in practice during a programs use, as far fewer will be tested that way than the length of any list you might own. Also, I think pax doesnt realize the purpose of prime algorithms, most of the time, is to test efficiency/speed rather than actually finding primes. – CogitoErgoCogitoSum Jul 23 '17 at 19:34
  • 2
    @CogitoErgoCogitoSum, agree that list of all primes will forever be out of date since I've seen the mathematical proof that they're infinite in number. However, the list of the first `x` primes will be unlikely to be incomplete once it's built :-) – paxdiablo Jul 25 '17 at 05:06
  • 1
    True, but there are better storage methods than reading from a file in a linear fashion. If you *really* want to read from a stored set of pre-generated primes, try a more complicated data structure that speeds up the problem. – CogitoErgoCogitoSum Jul 25 '17 at 14:03
9
bool isPrime(int n)
{
    // Corner cases
    if (n <= 1)  return false;
    if (n <= 3)  return true;

    // This is checked so that we can skip 
    // middle five numbers in below loop
    if (n%2 == 0 || n%3 == 0) return false;

    for (int i=5; i*i<=n; i=i+6)
        if (n%i == 0 || n%(i+2) == 0)
           return false;

    return true;
}

this is just c++ implementation of above AKS algorithm

wjandrea
  • 16,334
  • 5
  • 30
  • 53
saurabh kumar
  • 167
  • 1
  • 5
  • 2
    Its one of the most efficient deterministic algorithms Ive come across, yes, but its not an implementation of AKS. The AKS system is much newer than the algorithm outlined. It is arguably more efficient, but is somewhat difficult to implement, imo, on account of potentially astronomically large factorials / binomial coefficients. – CogitoErgoCogitoSum Jul 23 '17 at 19:41
  • How is this different from [Derri Leahi's (non-)answer](https://stackoverflow.com/users/7316867/derri-leahy) (other than C instead of Java)? How does this answer `What is the algorithm that produces a data structure with lowest memory consumption for the range (1, N]`? – greybeard Feb 03 '18 at 11:51
  • 1
    How does (n%i == 0 || n%(i+2) == 0) correspond to 6n+1 & 6n-1? – yesh Mar 08 '18 at 20:38
  • @YeshwanthVenkatesh: `How does (n%i == 0 || n%(i+2) == 0) correspond to 6n+1 & 6n-1?` part of the answer is different roles for `n`, the other is *6n+1 & 6n-1* equivalent to *(6n-1)+0* & (6n-1)+2*. – greybeard Mar 13 '18 at 21:43
  • Also note that this algorithm doesn't give the correct result for `5` and `7`. – Athan Clark Feb 14 '20 at 03:11
  • You may also be better off checking if the number is 6n+/-1 before the loop. If not, it's guaranteed to be non-prime, making the loop unnecessary. – paxdiablo May 13 '21 at 03:07
8

One can use sympy.

import sympy

sympy.ntheory.primetest.isprime(33393939393929292929292911111111)

True

From sympy docs. The first step is looking for trivial factors, which if found enables a quick return. Next, if the sieve is large enough, use bisection search on the sieve. For small numbers, a set of deterministic Miller-Rabin tests are performed with bases that are known to have no counterexamples in their range. Finally if the number is larger than 2^64, a strong BPSW test is performed. While this is a probable prime test and we believe counterexamples exist, there are no known counterexamples

LetzerWille
  • 4,414
  • 2
  • 18
  • 24
  • *An algorithm is a sequence of well-defined steps that defines an abstract solution to a problem.* - what is the *conceivable sequence of steps* in the code presented? What is its `memory consumption`? – greybeard Aug 26 '18 at 10:43
  • 2
    @greybeard. From sympy docs. The first step is looking for trivial factors, which if found enables a quick return. Next, if the sieve is large enough, use bisection search on the sieve. For small numbers, a set of deterministic Miller-Rabin tests are performed with bases that are known to have no counterexamples in their range. Finally if the number is larger than 2^64, a strong BPSW test is performed. While this is a probable prime test and we believe counterexamples exist, there are no known counterexamples. – LetzerWille Aug 26 '18 at 13:25
7

According to wikipedia, the Sieve of Eratosthenes has complexity O(n * (log n) * (log log n)) and requires O(n) memory - so it's a pretty good place to start if you aren't testing for especially large numbers.

matt b
  • 132,562
  • 64
  • 267
  • 334
  • Sorry I know my description is vague, I am not looking at SOE :) look at my comment @Michael – AraK Nov 26 '09 at 03:39
  • @AraK: You say you want a data structure to hold the primality status of all `n` up to a limit though. While dedicated primality testing functions are going to be faster for any given `n`, if you want to know all the results from 2 to `n`, with minimal cost, a Sieve of Eratosthenes with optimized storage (e.g. using a byte to represent the primality status of all numbers in a block of 30, after removing all numbers divisible by 2, 3 and 5, and hard-coding primes below 30) is how you'd populate it. Only practical to populate to a limit (e.g. w/4 GB RAM, you could store up to ~129 billion). – ShadowRanger Oct 14 '20 at 14:42
7

I compared the efficiency of the most popular suggestions to determine if a number is prime. I used python 3.6 on ubuntu 17.10; I tested with numbers up to 100.000 (you can test with bigger numbers using my code below).

This first plot compares the functions (which are explained further down in my answer), showing that the last functions do not grow as fast as the first one when increasing the numbers.

plot1

And in the second plot we can see that in case of prime numbers the time grows steadily, but non-prime numbers do not grow so fast in time (because most of them can be eliminated early on).

plot2

Here are the functions I used:

  1. this answer and this answer suggested a construct using all():

    def is_prime_1(n):
        return n > 1 and all(n % i for i in range(2, int(math.sqrt(n)) + 1))
    
  2. This answer used some kind of while loop:

    def is_prime_2(n):
        if n <= 1:
            return False
        if n == 2:
            return True
        if n == 3:
            return True
        if n % 2 == 0:
            return False
        if n % 3 == 0:
            return False
    
        i = 5
        w = 2
        while i * i <= n:
            if n % i == 0:
                return False
            i += w
            w = 6 - w
    
        return True
    
  3. This answer included a version with a for loop:

    def is_prime_3(n):
        if n <= 1:
            return False
    
        if n % 2 == 0 and n > 2:
            return False
    
        for i in range(3, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                return False
    
        return True
    
  4. And I mixed a few ideas from the other answers into a new one:

    def is_prime_4(n):
        if n <= 1:          # negative numbers, 0 or 1
            return False
        if n <= 3:          # 2 and 3
            return True
        if n % 2 == 0 or n % 3 == 0:
            return False
    
        for i in range(5, int(math.sqrt(n)) + 1, 2):
            if n % i == 0:
                return False
    
        return True
    

Here is my script to compare the variants:

import math
import pandas as pd
import seaborn as sns
import time
from matplotlib import pyplot as plt


def is_prime_1(n):
    ...
def is_prime_2(n):
    ...
def is_prime_3(n):
    ...
def is_prime_4(n):
    ...

default_func_list = (is_prime_1, is_prime_2, is_prime_3, is_prime_4)

def assert_equal_results(func_list=default_func_list, n):
    for i in range(-2, n):
        r_list = [f(i) for f in func_list]
        if not all(r == r_list[0] for r in r_list):
            print(i, r_list)
            raise ValueError
    print('all functions return the same results for integers up to {}'.format(n))

def compare_functions(func_list=default_func_list, n):
    result_list = []
    n_measurements = 3

    for f in func_list:
        for i in range(1, n + 1):
            ret_list = []
            t_sum = 0
            for _ in range(n_measurements):
                t_start = time.perf_counter()
                is_prime = f(i)
                t_end = time.perf_counter()

                ret_list.append(is_prime)
                t_sum += (t_end - t_start)

            is_prime = ret_list[0]
            assert all(ret == is_prime for ret in ret_list)
            result_list.append((f.__name__, i, is_prime, t_sum / n_measurements))

    df = pd.DataFrame(
        data=result_list,
        columns=['f', 'number', 'is_prime', 't_seconds'])
    df['t_micro_seconds'] = df['t_seconds'].map(lambda x: round(x * 10**6, 2))
    print('df.shape:', df.shape)

    print()
    print('', '-' * 41)
    print('| {:11s} | {:11s} | {:11s} |'.format(
        'is_prime', 'count', 'percent'))
    df_sub1 = df[df['f'] == 'is_prime_1']
    print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
        'all', df_sub1.shape[0], 100))
    for (is_prime, count) in df_sub1['is_prime'].value_counts().iteritems():
        print('| {:11s} | {:11,d} | {:9.1f} % |'.format(
            str(is_prime), count, count * 100 / df_sub1.shape[0]))
    print('', '-' * 41)

    print()
    print('', '-' * 69)
    print('| {:11s} | {:11s} | {:11s} | {:11s} | {:11s} |'.format(
        'f', 'is_prime', 't min (us)', 't mean (us)', 't max (us)'))
    for f, df_sub1 in df.groupby(['f', ]):
        col = df_sub1['t_micro_seconds']
        print('|{0}|{0}|{0}|{0}|{0}|'.format('-' * 13))
        print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
            f, 'all', col.min(), col.mean(), col.max()))
        for is_prime, df_sub2 in df_sub1.groupby(['is_prime', ]):
            col = df_sub2['t_micro_seconds']
            print('| {:11s} | {:11s} | {:11.2f} | {:11.2f} | {:11.2f} |'.format(
                f, str(is_prime), col.min(), col.mean(), col.max()))
    print('', '-' * 69)

    return df

Running the function compare_functions(n=10**5) (numbers up to 100.000) I get this output:

df.shape: (400000, 5)

 -----------------------------------------
| is_prime    | count       | percent     |
| all         |     100,000 |     100.0 % |
| False       |      90,408 |      90.4 % |
| True        |       9,592 |       9.6 % |
 -----------------------------------------

 ---------------------------------------------------------------------
| f           | is_prime    | t min (us)  | t mean (us) | t max (us)  |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1  | all         |        0.57 |        2.50 |      154.35 |
| is_prime_1  | False       |        0.57 |        1.52 |      154.35 |
| is_prime_1  | True        |        0.89 |       11.66 |       55.54 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2  | all         |        0.24 |        1.14 |      304.82 |
| is_prime_2  | False       |        0.24 |        0.56 |      304.82 |
| is_prime_2  | True        |        0.25 |        6.67 |       48.49 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3  | all         |        0.20 |        0.95 |       50.99 |
| is_prime_3  | False       |        0.20 |        0.60 |       40.62 |
| is_prime_3  | True        |        0.58 |        4.22 |       50.99 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4  | all         |        0.20 |        0.89 |       20.09 |
| is_prime_4  | False       |        0.21 |        0.53 |       14.63 |
| is_prime_4  | True        |        0.20 |        4.27 |       20.09 |
 ---------------------------------------------------------------------

Then, running the function compare_functions(n=10**6) (numbers up to 1.000.000) I get this output:

df.shape: (4000000, 5)

 -----------------------------------------
| is_prime    | count       | percent     |
| all         |   1,000,000 |     100.0 % |
| False       |     921,502 |      92.2 % |
| True        |      78,498 |       7.8 % |
 -----------------------------------------

 ---------------------------------------------------------------------
| f           | is_prime    | t min (us)  | t mean (us) | t max (us)  |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_1  | all         |        0.51 |        5.39 |     1414.87 |
| is_prime_1  | False       |        0.51 |        2.19 |      413.42 |
| is_prime_1  | True        |        0.87 |       42.98 |     1414.87 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_2  | all         |        0.24 |        2.65 |      612.69 |
| is_prime_2  | False       |        0.24 |        0.89 |      322.81 |
| is_prime_2  | True        |        0.24 |       23.27 |      612.69 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_3  | all         |        0.20 |        1.93 |       67.40 |
| is_prime_3  | False       |        0.20 |        0.82 |       61.39 |
| is_prime_3  | True        |        0.59 |       14.97 |       67.40 |
|-------------|-------------|-------------|-------------|-------------|
| is_prime_4  | all         |        0.18 |        1.88 |      332.13 |
| is_prime_4  | False       |        0.20 |        0.74 |      311.94 |
| is_prime_4  | True        |        0.18 |       15.23 |      332.13 |
 ---------------------------------------------------------------------

I used the following script to plot the results:

def plot_1(func_list=default_func_list, n):
    df_orig = compare_functions(func_list=func_list, n=n)
    df_filtered = df_orig[df_orig['t_micro_seconds'] <= 20]
    sns.lmplot(
        data=df_filtered, x='number', y='t_micro_seconds',
        col='f',
        # row='is_prime',
        markers='.',
        ci=None)

    plt.ticklabel_format(style='sci', axis='x', scilimits=(3, 3))
    plt.show()
Ralf
  • 13,322
  • 4
  • 31
  • 55
6

In Python 3:

def is_prime(a):
    if a < 2:
        return False
    elif a!=2 and a % 2 == 0:
        return False
    else:
        return all (a % i for i in range(3, int(a**0.5)+1))

Explanation: A prime number is a number only divisible by itself and 1. Ex: 2,3,5,7...

1) if a<2: if "a" is less than 2 it is not a prime.

2) elif a!=2 and a % 2 == 0: if "a" is divisible by 2 then its definitely not a prime. But if a=2 we don't want to evaluate that as it is a prime number. Hence the condition a!=2

3) return all (a % i for i in range(3, int(a0.5)+1) ):** First look at what all() command does in python. Starting from 3 we divide "a" till its square root (a**0.5). If "a" is divisible the output will be False. Why square root? Let's say a=16. The square root of 16 = 4. We don't need to evaluate till 15. We only need to check till 4 to say that it's not a prime.

Extra: A loop for finding all the prime number within a range.

for i in range(1,100):
    if is_prime(i):
        print("{} is a prime number".format(i))
Fouad Boukredine
  • 1,037
  • 11
  • 14
Deep grewal
  • 99
  • 2
  • 5
  • 1
    How does this differ from [Oleksandr Shmyheliuk's answer](https://stackoverflow.com/a/44785595/3789665)? (Both miss a "step 2" in `range()`…) – greybeard Feb 25 '18 at 07:53
  • 1
    If a number is even then it is not a prime (excluding 2). So no need to check for even numbers. This will be much faster if you want to get prime number within a range. It will straight up exclude the even numbers. – Deep grewal Feb 27 '18 at 09:41
3

Python 3:

def is_prime(a):
    return a > 1 and all(a % i for i in range(2, int(a**0.5) + 1))
3

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.

Community
  • 1
  • 1
Piotr Dabkowski
  • 4,878
  • 4
  • 35
  • 45
  • This is the Miller test. The Miller-Rabin test is the probabilistic version where randomly selected bases are tested until sufficient confidence is achieved. Also, the Miller test is not dependent on the Riemann Hypothesis directly, but the Generalized Riemann Hypothesis (GRH) for quadratic Diriclet characters (I know it's a mouthful, and I don't understand it either). Which means a potential proof for the Riemann Hypothesis may not even apply to the GRH, and hence not prove the Miller test correct. Even worse case would be of course if the GRH is disproved. – Arne Vogel May 06 '19 at 18:29
2

Way too late to the party, but hope this helps. This is relevant if you are looking for big primes:

To test large odd numbers you need to use the Fermat-test and/or Miller-Rabin test.

These tests use modular exponentiation which is quite expensive, for n bits exponentiation you need at least n big int multiplication and n big int divison. Which means the complexity of modular exponentiation is O(n³).

So before using the big guns, you need to do quite a few trial divisions. But don't do it naively, there is a way to do them fast. First multiply as many primes together as many fits into a the words you use for the big integers. If you use 32 bit words, multiply 3*5*7*11*13*17*19*23*29=3234846615 and compute the greatest common divisor with the number you test using the Euclidean algorithm. After the first step the number is reduced below the word size and continue the algorithm without performing complete big integer divisions. If the GCD != 1, that means one of the primes you multiplied together divides the number, so you have a proof it's not prime. Then continue with 31*37*41*43*47 = 95041567, and so on.

Once you tested several hundred (or thousand) primes this way, you can do 40 rounds of Miller-Rabin test to confirm the number is prime, after 40 rounds you can be certain the number is prime there is only 2^-80 chance it's not (it's more likely your hardware malfunctions...).

Calmarius
  • 16,155
  • 15
  • 95
  • 134
1

I have got a prime function which works until (2^61)-1 Here:

from math import sqrt
def isprime(num): num > 1 and return all(num % x for x in range(2, int(sqrt(num)+1)))

Explanation:

The all() function can be redefined to this:

def all(variables):
    for element in variables:
        if not element: return False
    return True

The all() function just goes through a series of bools / numbers and returns False if it sees 0 or False.

The sqrt() function is just doing the square root of a number.

For example:

>>> from math import sqrt
>>> sqrt(9)
>>> 3
>>> sqrt(100)
>>> 10

The num % x part returns the remainder of num / x.

Finally, range(2, int(sqrt(num))) means that it will create a list that starts at 2 and ends at int(sqrt(num)+1)

For more information about range, have a look at this website!

The num > 1 part is just checking if the variable num is larger than 1, becuase 1 and 0 are not considered prime numbers.

I hope this helped :)

  • Please argue how this is `the best` algorithm, or even a *good* one. – greybeard May 11 '18 at 18:25
  • @greybeard , Most prime functions here dont go up to (2^31)-1 or takes too long for high numbers, but mine works until (2^61)-1, so you can check if a number is prime with a wider range of numbers. – WhyAreYouReadingThis May 14 '18 at 08:15
1

In Python:

def is_prime(n):
    return not any(n % p == 0 for p in range(2, int(math.sqrt(n)) + 1))

A more direct conversion from mathematical formalism to Python would use all(n % p != 0... ), but that requires strict evaluation of all values of p. The not any version can terminate early if a True value is found.

Vlad Bezden
  • 59,971
  • 18
  • 206
  • 157
  • Wrt _"all(n % p != 0... ), but that requires strict evaluation of all values of p"_ - that's incorrect. `any` and `all` will both **exit early**. So at the first `p` where `n % p` is `0`, `all` would exit. – aneroid Jan 08 '19 at 21:02
1

best algorithm for Primes number javascript

 function isPrime(num) {
      if (num <= 1) return false;
      else if (num <= 3) return true;
      else if (num % 2 == 0 || num % 3 == 0) return false;
      var i = 5;
      while (i * i <= num) {
        if (num % i == 0 || num % (i + 2) == 0) return false;
        i += 6;
      }
      return true
    }
1
import math
import time


def check_prime(n):

    if n == 1:
        return False

    if n == 2:
        return True

    if n % 2 == 0:
        return False

    from_i = 3
    to_i = math.sqrt(n) + 1

    for i in range(from_i, int(to_i), 2):
        if n % i == 0:
            return False
    return True
aedry
  • 157
  • 2
  • 14
1

A prime number is any number that is only divisible by 1 and itself. All other numbers are called composite.

The simplest way, of finding a prime number, is to check if the input number is a composite number:

    function isPrime(number) {
        // Check if a number is composite
        for (let i = 2; i < number; i++) {
            if (number % i === 0) {
                return false;
            }
        }
        // Return true for prime numbers
        return true;
    }

The program has to divide the value of number by all the whole numbers from 1 and up to the its value. If this number can be divided evenly not only by one and itself it is a composite number.

The initial value of the variable i has to be 2 because both prime and composite numbers can be evenly divided by 1.

    for (let i = 2; i < number; i++)

Then i is less than number for the same reason. Both prime and composite numbers can be evenly divided by themselves. Therefore there is no reason to check it.

Then we check whether the variable can be divided evenly by using the remainder operator.

    if (number % i === 0) {
        return false;
    }

If the remainder is zero it means that number can be divided evenly, hence being a composite number and returning false.

If the entered number didn't meet the condition, it means it's a prime number and the function returns true.

  • 1
    (While I think `simplest` one valid interpretation of *best*:) The question is *What is the best algorithm for checking if a number is prime?*: Is checking for divisibility where `number / 2 < i < number` advantageous? What about `number < i*i`? What do the understandable ones of the other 3³ answers say? – greybeard Jul 27 '19 at 17:23
  • Just to be clear, 1 is neither prime *nor composite.* And primes are drawn from positive integers. – paxdiablo May 13 '21 at 03:09
1

Let me suggest you the perfect solution for 64 bit integers. Sorry to use C#. You have not already specified it as python in your first post. I hope you can find a simple modPow function and analyze it easily.

public static bool IsPrime(ulong number)
{
    return number == 2 
        ? true 
        : (BigInterger.ModPow(2, number, number) == 2 
            ? (number & 1 != 0 && BinarySearchInA001567(number) == false) 
            : false)
}

public static bool BinarySearchInA001567(ulong number)
{
    // Is number in list?
    // todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
    // Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}
0

Smallest memory? This isn't smallest, but is a step in the right direction.

class PrimeDictionary {
    BitArray bits;

    public PrimeDictionary(int n) {
        bits = new BitArray(n + 1);
        for (int i = 0; 2 * i + 3 <= n; i++) {
            bits.Set(i, CheckPrimality(2 * i + 3));
        }
    }

    public PrimeDictionary(IEnumerable<int> primes) {
        bits = new BitArray(primes.Max());
        foreach(var prime in primes.Where(p => p != 2)) {
            bits.Set((prime - 3) / 2, true);
        }
    }

    public bool IsPrime(int k) {
        if (k == 2) {
            return true;
        }
        if (k % 2 == 0) {
            return false;
        }
        return bits[(k - 3) / 2];
    }
}

Of course, you have to specify the definition of CheckPrimality.

jason
  • 220,745
  • 31
  • 400
  • 507
0

I think one of the fastest is my method that I made.

void prime(long long int number) {
    // Establishing Variables
    long long int i = 5;
    int w = 2;
    const long long int lim = sqrt(number);

    // Gets 2 and 3 out of the way
    if (number == 1) { cout << number << " is hard to classify. \n";  return; }
    if (number == 2) { cout << number << " is Prime. \n";  return; }
    if (number == 3) { cout << number << " is Prime. \n";  return; }

    // Tests Odd Ball Factors
    if (number % 2 == 0) { cout << number << " is not Prime. \n";  return; }
    if (number % 3 == 0) { cout << number << " is not Prime. \n";  return; }

    while (i <= lim) {
        if (number % i == 0) { cout << number << " is not Prime. \n";  return; }
        // Tests Number
        i = i + w; // Increments number
        w = 6 - i; // We already tested 2 and 3
        // So this removes testing multepules of this
    }
    cout << number << " is Prime. \n"; return;
}
Spl1ce
  • 19
  • 1
0

Similar idea to the AKS algorithm which has been mentioned

public static boolean isPrime(int n) {

    if(n == 2 || n == 3) return true;
    if((n & 1 ) == 0 || n % 3 == 0) return false;
    int limit = (int)Math.sqrt(n) + 1;
    for(int i = 5, w = 2; i <= limit; i += w, w = 6 - w) {
        if(n % i == 0) return false;
        numChecks++;
    }
    return true;
}
0

To find if the number or numbers in a range is/are prime.

#!usr/bin/python3

def prime_check(*args):
    for arg in args:
        if arg > 1:     # prime numbers are greater than 1
            for i in range(2,arg):   # check for factors
                if(arg % i) == 0:
                    print(arg,"is not Prime")
                    print(i,"times",arg//i,"is",arg)
                    break
            else:
                print(arg,"is Prime")
                
            # if input number is less than
            # or equal to 1, it is not prime
        else:
            print(arg,"is not Prime")
    return
    
# Calling Now
prime_check(*list(range(101)))  # This will check all the numbers in range 0 to 100 
prime_check(#anynumber)         # Put any number while calling it will check.
Community
  • 1
  • 1
0
myInp=int(input("Enter a number: "))
if myInp==1:
    print("The number {} is neither a prime not composite no".format(myInp))
elif myInp>1:
    for i in range(2,myInp//2+1):
        if myInp%i==0:
            print("The Number {} is not a prime no".format(myInp))
            print("Because",i,"times",myInp//i,"is",myInp)
            break
    else:
        print("The Number {} is a prime no".format(myInp))
else:
    print("Alas the no {} is a not a prime no".format(myInp))
DKB
  • 1
  • 1
  • 1
    When you write an answer, even if it's correct, please also write a bit explaining what you are doing, and why. This way people reading your answer can grasp easier what you have solved. Thank you! – kim Mar 27 '18 at 20:34
  • 1
    Sure Kim ,thank you for pointing that out .This is my first program in Stackoverflow henceforth i will add appropriate comments and explanation . – DKB Mar 28 '18 at 19:14
0
public static boolean isPrime(int number) {
 if(number < 2)
   return false;
 else if(number == 2 || number == 3)
        return true;
      else {
        for(int i=2;i<=number/2;i++)
           if(number%i == 0)
             return false;
           else if(i==number/2)
                return true;
      }
    return false;
}
gaurav
  • 11
0

You could try something like this.

def main():
    try:
        user_in = int(input("Enter a number to determine whether the number is prime or not: "))
    except ValueError:
        print()
        print("You must enter a number!")
        print()
        return
    list_range = list(range(2,user_in+1))
    divisor_list = []
    for number in list_range:
        if user_in%number==0:
            divisor_list.append(number)
    if len(divisor_list) < 2:
        print(user_in, "is a prime number!")
        return
    else:
        print(user_in, "is not a prime number!")
        return
main()
  • This is a terrible solution for testing primeness. Once you find *one* divisor, you know the answer, but this code finds *all* the divisors and then decides! And it ignores the OP's request for a boolean predicate as it always returns `None`. – cdlane Oct 01 '18 at 16:00
  • @cdlane i know this isnt boolean return function, i am still a beginner in python and i know it isnt perfect, thanks for commenting anyway – Patrick Jane Oct 02 '18 at 16:13
0

Most of previous answers are correct but here is one more way to test to see a number is prime number. As refresher, prime numbers are whole number greater than 1 whose only factors are 1 and itself.(source)

Solution:

Typically you can build a loop and start testing your number to see if it's divisible by 1,2,3 ...up to the number you are testing ...etc but to reduce the time to check, you can divide your number by half of the value of your number because a number cannot be exactly divisible by anything above half of it's value. Example if you want to see 100 is a prime number you can loop through up to 50.

Actual code:

def find_prime(number):
    if(number ==1):
        return False
    # we are dividiing and rounding and then adding the remainder to increment !
    # to cover not fully divisible value to go up forexample 23 becomes 11
    stop=number//2+number%2
    #loop through up to the half of the values
    for item in range(2,stop):
        if number%item==0:
           return False
        print(number)
    return True


if(find_prime(3)):
    print("it's a prime number !!")
else:
    print("it's not a prime")  
grepit
  • 16,512
  • 5
  • 83
  • 71
  • You only need to check to the square root of the number, which is quite a bit smaller than half the number. E.g. for n=100 you only need to check to 10, not 50. Why? At exactly the square root, the two factors are equal. For any other factor one will be less than sqrt(n) and the other larger. So if we haven't seen one by the time we have checkup up to and including sqrt(n), we won't find one after. – DanaJ Jan 23 '19 at 22:34
0

We can use java streams to implement this in O(sqrt(n)); Consider that noneMatch is a shortCircuiting method that stops the operation when finds it unnecessary for determining the result:

Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(n == 2 ? "Prime" : IntStream.rangeClosed(2, ((int)(Math.sqrt(n)) + 1)).noneMatch(a -> n % a == 0) ? "Prime" : "Not Prime");
0

With help of Java-8 streams and lambdas, it can be implemented like this in just few lines:

public static boolean isPrime(int candidate){
        int candidateRoot = (int) Math.sqrt( (double) candidate);
        return IntStream.range(2,candidateRoot)
                .boxed().noneMatch(x -> candidate % x == 0);
    }

Performance should be close to O(sqrt(N)). Maybe someone find it useful.

Stefan Repcek
  • 2,285
  • 2
  • 18
  • 26
  • "range" should be replaced with "rangeClosed" to include candidateRoot. Also candidate < 2 case should be handled. – udalmik Jan 27 '19 at 09:47
  • How is this different from [alirezafnatica's prior answer](https://stackoverflow.com/a/53002968/3789665)? – greybeard Jul 28 '19 at 02:02
0

Here's my take on the answer:

def isprime(num):
    return num <= 3 or (num + 1) % 6 == 0 or (num - 1) % 6 == 0

The function will return True if any of the properties below are True. Those properties mathematically define what a prime is.

  1. The number is less than or equal to 3
  2. The number + 1 is divisible by 6
  3. The number - 1 is divisible by 6
Richie Bendall
  • 3,783
  • 2
  • 24
  • 36
  • `>>> isprime(25)` returns `True`. You are checking a very simple _necessary_ condition (divisibility by 2 or 3) but this is not _sufficient_. – DanaJ Jan 23 '19 at 22:30
  • Nice, you are matching by this property: every prime number greater than 3 is of the form 6n+1 or 6n+5, but there exists numbers (as 25) that are of the form 6n+1 or 6n+5, but they are not prime – Luis Felipe Jun 27 '20 at 03:54
0
bool isPrime(int n) {
if(n <= 3)
    return (n > 1)==0? false: true;
else if(n%2 == 0 || n%3 == 0)
    return false;

int i = 5;

while(i * i <= n){
    if(n%i == 0 || (n%(i+2) == 0))
        return false;
    i = i + 6;
}

return true;
}

for any number, the minimum iterations to check if the number is prime or not can be from 2 to square root of the number. To reduce the iterations, even more, we can check if the number is divisible by 2 or 3 as maximum numbers can be eliminated by checking if the number is divisible by 2 or 3. Further any prime number greater than 3 can be expressed as 6k+1 or 6k-1. So the iteration can go from 6k+1 to the square root of the number.

Satyam Anand
  • 109
  • 7
  • 1
    It would be better if you added some explanation to your answer using [edit]. It might not be clear to many readers why your answer is a good one, and they could learn from you if you explained more. – Brian Tompsett - 汤莱恩 Jul 22 '20 at 11:53
0

here is the fastest way to do it:

def divisors(integer):
    result = []
    i = 2 
    j = integer/2
    while(i <= j):
        if integer % i == 0:
            result.append(i)
            if i != integer//i:
                result.append(integer//i)
        i += 1
        j = integer//i
    if len(result) > 0:
        return sorted(result)
    else:
        return f"{integer} is prime"
-2

When I have to do a fast verification, I write this simple code based on the basic division between numbers lower than square root of input.

def isprime(n):
    if n%2==0:
        return n==2
    else:
        cota = int(n**0.5)+1
        for ind in range(3,2,cota):
            if n%ind==0:
                print(ind)
                return False
    is_one = n==1
    return True != is_one

isprime(22783)
  • The last True != n==1 is to avoid the case n=1.
Luis Felipe
  • 329
  • 3
  • 17
-4

First Rule of a Prime: If divided by 2 equals a whole number or integer No its not prime.

Fastest method to Know using any computer language is type matching using strings not math. Match the DOT in a stringed Float.

  • Divide it by 2,,, n = n / 2
  • Convert this to a string,,, n = string(n)
  • if "." in n: { printf "Yes I Am Prime !"
    }
Brad Larson
  • 168,330
  • 45
  • 388
  • 563
rodeone2
  • 71
  • 1
  • 5
  • 3
    The "first rule of a prime" is that if *any* whole number greater than one divides it, then it's not a prime. Testing it with just 2 isn't enough. And converting a number to a string to test if it's a whole number is possibly the slowest method you could reasonably come up with. – JJJ Jan 07 '19 at 15:12