Como criar o mapeamento mais compacto n → isprime (n) até um limite N?


152

Naturalmente, pois bool isprime(number)haveria uma estrutura de dados que eu poderia consultar.
Eu defino o melhor algoritmo , para ser o algoritmo que produz uma estrutura de dados com menor consumo de memória para o intervalo (1, N], onde N é uma constante.
Apenas um exemplo do que estou procurando: eu poderia representar todos os números ímpares com um bit, por exemplo, para o intervalo determinado de números (1, 10], começa em 3:1110

O dicionário a seguir pode ser espremido mais, certo? Eu poderia eliminar múltiplos de cinco com algum trabalho, mas os números que terminam com 1, 3, 7 ou 9 devem estar lá na matriz de bits.

Como resolvo o problema?


3
Seu pedido é um pouco vago. Você fornece uma assinatura que testa um único número, mas depois solicita uma estrutura de dados de (1, N]. Deseja um algoritmo que gere um dicionário <int, bool> ou apenas uma função de uma tentativa que verifique se um único número é primo?
Michael Haren

@ Michael Desculpe, essa é a melhor descrição que eu poderia ter. O que estou procurando é exatamente o que você está dizendo: um dicionário booleano. Gostaria de minimizar o espaço do dicionário. Obrigado :)
AraK

1
Se é isso que você está procurando, já foi perguntado: stackoverflow.com/questions/1032427/…
Ben S

14
Você precisaria Pergunte ao NSA
Charles Bretana

Respostas:


79

Existem muitas maneiras de fazer o teste de primalidade .

Não há realmente uma estrutura de dados para você consultar. Se você tem muitos números para testar, provavelmente deve executar um teste probabilístico, pois esses são mais rápidos e, em seguida, segui-lo com um teste determinístico para garantir que o número seja primo.

Você deve saber que a matemática por trás dos algoritmos mais rápidos não é para os fracos de coração.


4
Miller-Rabin é um teste probabilístico rápido e popular para começar.
Qd #

214

O algoritmo mais rápido para o teste geral geral é o AKS . O artigo da Wikipedia descreve detalhadamente e links para o artigo original.

Se você deseja encontrar grandes números, procure números primos que tenham formas especiais como números primos de Mersenne .

O algoritmo que eu costumo implementar (fácil de entender e codificar) é o seguinte (em 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

É uma variante do O(sqrt(N))algoritmo clássico . Ele usa o fato de que um primo (exceto 2 e 3) é de forma 6k - 1ou 6k + 1olha apenas para os divisores dessa forma.

Às vezes, se eu realmente quero velocidade e o alcance é limitado , implemento um teste pseudo-primo baseado no pequeno teorema de Fermat . Se eu realmente quiser mais velocidade (ou seja, evitar o algoritmo O (sqrt (N)) por completo), pré-calculo os falsos positivos (consulte os números de Carmichael ) e faço uma pesquisa binária. Este é de longe o teste mais rápido que já implementei, a única desvantagem é que o alcance é limitado.


7
Duas perguntas: Você pode explicar melhor o que as variáveis ie wsão, e o que se entende pela forma 6k-1e 6k+1? Obrigado pela sua compreensão e o exemplo de código (o que eu estou tentando entender)
Freedom_Ben

6
@Freedom_Ben Aqui está, quora.com/…
Alan Dong

6
Não seria melhor calcular o sqrtde numa vez e compará i-lo a ele, em vez de calcular i * itodos os ciclos do loop?
pedros

3
@Dschoni ... mas você não pode ajustar a implementação mais rápida nos campos de comentários aqui para compartilhar conosco?
GreenAsJade 14/02

3
Ele falha para o número 1 :(
Damjan Pavlica

27

O melhor método, na minha opinião, é usar o que foi antes.

Existem listas dos primeiros Nnúmeros primos na internet com Naté pelo menos cinquenta milhões . Baixe os arquivos e use-os; é provável que seja muito mais rápido do que qualquer outro método que você criar.

Se você deseja um algoritmo real para criar seus próprios números primos, a Wikipedia tem todo tipo de coisas boas sobre números primos aqui , incluindo links para os vários métodos para fazê-lo e teste aqui. , tanto métodos baseados em probabilidade quanto determinantes rapidamente.

Deveria haver um esforço conjunto para encontrar o primeiro bilhão (ou mais) de números primos e publicá-los na rede em algum lugar para que as pessoas possam parar de fazer o mesmo trabalho repetidamente e repetidamente e ... :-)


2
@hamedbh: Interessante. Você já tentou baixar esses arquivos? Parece que eles não existem.
21416

Ainda não, receio: eu estava apenas olhando rapidamente durante o meu horário de almoço. Excluirei esse link caso haja algo malicioso. Sinto muito, eu realmente deveria ter verificado isso primeiro.
quer

1
Essas listas fazem existir. Eu os vi anos atrás, mas nunca me importei em baixá-los. A verdade é que eles ocupam muito espaço (relativamente falando) e não devem ser incluídos nos programas vendidos ou distribuídos. Além disso, eles serão sempre e para sempre incompletos. Faz mais sentido testar cada número que aparece na prática durante o uso de um programa, pois menos serão testados dessa maneira do que o tamanho de qualquer lista que você possua. Além disso, acho que o pax não percebe que o objetivo dos algoritmos primos, na maioria das vezes, é testar a eficiência / velocidade, em vez de realmente encontrar números primos.
CogitoErgoCogitoSum

2
@CogitoErgoCogitoSum, concordo que a lista de todos os números primos ficará para sempre desatualizada desde que eu vi a prova matemática de que eles são infinitos em número. No entanto, xé improvável que a lista dos primeiros números primos fique incompleta depois de criada :-) #
384

1
É verdade, mas existem métodos de armazenamento melhores do que a leitura de um arquivo de maneira linear. Se você realmente deseja ler de um conjunto armazenado de números primos pré-gerados, tente uma estrutura de dados mais complicada que acelere o problema.
CogitoErgoCogitoSum

10
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;
}

esta é apenas implementação em c ++ do algoritmo AKS acima


1
É um dos algoritmos determinísticos mais eficientes que já encontrei, sim, mas não é uma implementação do AKS. O sistema AKS é muito mais recente que o algoritmo descrito. É sem dúvida mais eficiente, mas é um pouco difícil de implementar, devido a fatores fatoriais / coeficientes binomiais potencialmente astronomicamente grandes.
CogitoErgoCogitoSum

Como isso é diferente da resposta (não) de Derri Leahi (diferente de C em vez de Java)? Como isso responde What is the algorithm that produces a data structure with lowest memory consumption for the range (1, N]?
greybeard

1
Como (n% i == 0 || n% (i + 2) == 0) corresponde a 6n + 1 e 6n-1?
yesh

@YeshwanthVenkatesh: How does (n%i == 0 || n%(i+2) == 0) correspond to 6n+1 & 6n-1?parte da resposta tem diferentes papéis n, a outra é 6n + 1 e 6n-1 equivalente a (6n-1) +0 e (6n-1) + 2 *.
precisa

Observe também que esse algoritmo não fornece o resultado correto para 5e 7.
Athan Clark 14/02

7

Comparei a eficiência das sugestões mais populares para determinar se um número é primo. I utilizado python 3.6em ubuntu 17.10; Testei com números de até 100.000 (você pode testar com números maiores usando o meu código abaixo).

Este primeiro gráfico compara as funções (que são explicadas mais adiante na minha resposta), mostrando que as últimas funções não crescem tão rápido quanto a primeira ao aumentar os números.

plot1

E no segundo gráfico, podemos ver que, no caso de números primos, o tempo cresce constantemente, mas os números não primos não crescem tão rápido no tempo (porque a maioria deles pode ser eliminada desde o início).

plot2

Aqui estão as funções que eu usei:

  1. esta resposta e esta resposta sugeriram uma construção usando all():

    def is_prime_1(n):
        return n > 1 and all(n % i for i in range(2, int(math.sqrt(n)) + 1))
    
  2. Esta resposta usou algum tipo de loop while:

    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. Esta resposta incluiu uma versão com um forloop:

    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. E misturei algumas idéias das outras respostas em uma nova:

    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
    

Aqui está o meu script para comparar as variantes:

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

Executando a função compare_functions(n=10**5)(números até 100.000), recebo esta saída:

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 |
 ---------------------------------------------------------------------

Então, executando a função compare_functions(n=10**6)(números até 1.000.000), recebo esta saída:

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 |
 ---------------------------------------------------------------------

Eu usei o seguinte script para plotar os resultados:

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()


6

Pode-se usar o sympy .

import sympy

sympy.ntheory.primetest.isprime(33393939393929292929292911111111)

True

De documentos sympy. O primeiro passo é procurar por fatores triviais que, se encontrados, permitem um retorno rápido. Em seguida, se a peneira for grande o suficiente, use a pesquisa por bissecção na peneira. Para números pequenos, um conjunto de testes determinísticos de Miller-Rabin é realizado com bases que sabidamente não possuem contra-exemplos em seu intervalo. Finalmente, se o número for maior que 2 ^ 64, um forte teste BPSW é realizado. Embora este seja um provável teste principal e acreditemos que existem contra-exemplos, não existem contra-exemplos conhecidos


Um algoritmo é uma sequência de etapas bem definidas que define uma solução abstrata para um problema. - qual é a sequência concebível de etapas no código apresentado? Qual é o seu memory consumption?
precisa saber é o seguinte

2
@greybeard. De documentos sympy. O primeiro passo é procurar por fatores triviais que, se encontrados, permitem um retorno rápido. Em seguida, se a peneira for grande o suficiente, use a pesquisa por bissecção na peneira. Para números pequenos, um conjunto de testes determinísticos de Miller-Rabin é realizado com bases conhecidas por não terem contra-exemplos em seu intervalo. Finalmente, se o número for maior que 2 ^ 64, um forte teste BPSW é realizado. Embora este seja um provável teste principal e acreditemos que existem contra-exemplos, não existem contra-exemplos conhecidos.
precisa saber é o seguinte

6

No 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))

Explicação: Um número primo é um número divisível por si só e 1. Ex: 2,3,5,7 ...

1) se a <2: se "a" for menor que 2, não será primo.

2) elif a! = 2 e a% 2 == 0: se "a" é divisível por 2, então definitivamente não é um primo. Mas se a = 2, não queremos avaliar isso, pois é um número primo. Portanto, a condição a! = 2

3) retorne tudo (a% i para i no intervalo (3, int (a 0,5) +1)): ** Primeiro observe o que o comando all () faz no python. A partir de 3, dividimos "a" até a raiz quadrada (a ** 0,5). Se "a" é divisível, a saída será False. Por que raiz quadrada? Digamos que a = 16. A raiz quadrada de 16 = 4. Não precisamos avaliar até 15. Só precisamos verificar até 4 para dizer que não é primo.

Extra: Um loop para encontrar todo o número primo dentro de um intervalo.

for i in range(1,100):
    if is_prime(i):
        print("{} is a prime number".format(i))

1
Como isso difere da resposta de Oleksandr Shmyheliuk ? (Ambos perdem um "passo 2" em range()…) #
greybeard

1
Se um número é par, não é primo (excluindo 2). Portanto, não há necessidade de verificar números pares. Isso será muito mais rápido se você quiser obter o número primo dentro de um intervalo. Ele excluirá os números pares diretamente.
Crescimento profundo


3

Para números grandes, você não pode simplesmente verificar ingenuamente se o número candidato N é divisível por nenhum dos números menores que sqrt (N). Existem testes muito mais escalonáveis ​​disponíveis, como o teste de primalidade de Miller-Rabin . Abaixo você tem implementação em 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

Você pode usá-lo para encontrar grandes números primos:

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

# 10000000000000000000000000000000000000000000000000000000000000000000000000133 is a prime!

Se você estiver testando números inteiros aleatórios, provavelmente desejará primeiro testar se o número candidato é divisível por qualquer um dos primos menores que, digamos 1000, antes de ligar para Miller-Rabin. Isso ajudará você a filtrar não-primos óbvios, como 10444344345.


Este é o teste de Miller. O teste de Miller-Rabin é a versão probabilística em que bases selecionadas aleatoriamente são testadas até que seja alcançada confiança suficiente. Além disso, o teste de Miller não depende diretamente da hipótese de Riemann, mas da hipótese generalizada de Riemann (GRH) para caracteres quadráticos do Diriclet (eu sei que é um bocado e também não o entendo). O que significa que uma prova potencial para a hipótese de Riemann pode nem se aplicar ao GRH e, portanto, não provar que o teste de Miller está correto. Pior ainda seria, obviamente, se o GRH for refutado.
Arne Vogel

2

Tarde demais para a festa, mas espero que isso ajude. Isso é relevante se você estiver procurando por números primos grandes:

Para testar grandes números ímpares, você precisa usar o teste de Fermat e / ou o teste de Miller-Rabin.

Esses testes usam exponenciação modular que é bastante cara, para nexponenciação de bits você precisa de pelo menos ngrande multiplicação int en big int divison. O que significa que a complexidade da exponenciação modular é O (n³).

Portanto, antes de usar as armas grandes, você precisa fazer algumas divisões de teste. Mas não faça isso de forma ingênua, há uma maneira de fazê-los rapidamente. Primeiro multiplique o número de primos e o número de palavras que você usar para os números inteiros grandes. Se você usar palavras de 32 bits, multiplique 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 = 3234846615 e calcule o maior divisor comum com o número que você testa usando o algoritmo euclidiano. Após o primeiro passo, o número é reduzido abaixo do tamanho da palavra e continua o algoritmo sem executar grandes divisões inteiras grandes. Se o GCD! = 1, significa que um dos números primos que você multiplicou divide o número, para que você tenha uma prova de que não é primo. Continue com 31 * 37 * 41 * 43 * 47 = 95041567 e assim por diante.

Depois de testar várias centenas (ou milhares) de números primos dessa maneira, você pode fazer 40 rodadas do teste de Miller-Rabin para confirmar que o número é primo. Após 40 rodadas, você pode ter certeza de que o número é primo. não (é mais provável que o seu hardware não funcione corretamente).


1

Eu tenho uma função principal que funciona até (2 ^ 61) -1 Aqui:

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

Explicação:

A all()função pode ser redefinida para isso:

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

A all()função apenas passa por uma série de bools / números e retorna Falsese vê 0 ou False.

A sqrt()função está apenas fazendo a raiz quadrada de um número.

Por exemplo:

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

o num % x peça retorna o restante de num / x.

Finalmente, range(2, int(sqrt(num)))significa que ele criará uma lista que começa em 2 e termina emint(sqrt(num)+1)

Para obter mais informações sobre o alcance, dê uma olhada neste site !

o num > 1 peça está apenas verificando se a variável numé maior que 1, porque 1 e 0 não são considerados números primos.

Espero que isso tenha ajudado :)


Por favor, discuta como isso é um the bestalgoritmo, ou mesmo um bom .
Greybeard

@greybeard, a maioria das funções primárias aqui não vai até (2 ^ 31) -1 ou demora muito para números altos, mas a minha funciona até (2 ^ 61) -1, para que você possa verificar se um número é primo com um número maior intervalo de números.
precisa saber é o seguinte

1

Em Python:

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

Uma conversão mais direta do formalismo matemático para Python usaria tudo (n% p! = 0 ...) , mas isso requer avaliação rigorosa de todos os valores de p. A versão que não existe pode terminar mais cedo se um valor True for encontrado.


Wrt "all (n% p! = 0 ...), mas isso requer avaliação rigorosa de todos os valores de p" - isso está incorreto. anye allambos sairão mais cedo . Então, no primeiro ponde n % pestá 0, alliria sair.
aneroid

1

melhor algoritmo para o número Primes 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

1

Um número primo é qualquer número que é divisível apenas por 1 e ele próprio. Todos os outros números são chamados compostos .

A maneira mais simples, de encontrar um número primo, é verificar se o número de entrada é um número composto:

    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;
    }

O programa precisa dividir o valor de number todos os números inteiros de 1 e até o seu valor. Se esse número puder ser dividido igualmente, não apenas por um e por si, é um número composto.

O valor inicial da variável ideve ser 2 porque os números primos e compostos podem ser divididos igualmente por 1.

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

Então ié menor quenumber pela mesma razão. Os números primos e compostos podem ser divididos igualmente por si mesmos. Portanto, não há razão para verificá-lo.

Em seguida, verificamos se a variável pode ser dividida uniformemente usando o operador restante.

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

Se o restante for zero, significa que number pode ser dividido igualmente, sendo portanto um número composto e retornando falso.

Se o número digitado não atender à condição, significa que é um número primo e a função retorna verdadeira.


1
(Embora eu ache simplestuma interpretação válida de melhor :) A questão é que é o melhor algoritmo para verificar se um número é primo? : A verificação da divisibilidade é number / 2 < i < numbervantajosa? Que tal number < i*i? O que dizem os compreensíveis das outras 3³ respostas?
27619

1

Deixe-me sugerir a solução perfeita para números inteiros de 64 bits. Desculpe usar C #. Você ainda não o especificou como python em sua primeira postagem. Espero que você possa encontrar uma função modPow simples e analisá-la facilmente.

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
}

1
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;
}

para qualquer número, as iterações mínimas para verificar se o número é primo ou não podem ser de 2 a raiz quadrada do número. Para reduzir ainda mais as iterações, podemos verificar se o número é divisível por 2 ou 3, pois o número máximo pode ser eliminado, verificando se o número é divisível por 2 ou 3. Além disso, qualquer número primo maior que 3 pode ser expresso como 6k +1 ou 6k-1. Portanto, a iteração pode ir de 6k + 1 à raiz quadrada do número.


1
Seria melhor se você adicionasse algumas explicações à sua resposta usando a edição . Pode não estar claro para muitos leitores por que sua resposta é boa e eles podem aprender com você se você explicar mais.
Brian Tompsett - 莱恩 莱恩

0

Menor memória? Isso não é o menor, mas é um passo na direção certa.

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];
    }
}

Claro, você deve especificar a definição de CheckPrimality.


0

Eu acho que um dos mais rápidos é o meu método que eu fiz.

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;
}

1
um erro pode ser ... 6 - i?
Hmmm

0

Idéia semelhante ao algoritmo AKS que foi mencionado

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;
}

1
Nenhuma relação com o algoritmo AKS .
greybeard

No loop for, você não precisa marcar "i <= limit", basta checar "i <limit". Portanto, a cada iteração, você faz uma comparação a menos.
Andrushenko Alexander

0

Para descobrir se o número ou números em um intervalo é / são primos.

#!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.

Executar este código que vai funcionar tanto para uma lista e um número específico
Harsh Singh

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))

1
Quando você escrever uma resposta, mesmo que esteja correta, escreva um pouco explicando o que está fazendo e por quê. Dessa forma, as pessoas que leem sua resposta podem entender mais facilmente o que você resolveu. Obrigado!
kim

1
Claro Kim, obrigado por apontar isso. Este é o meu primeiro programa no Stackoverflow a partir de agora, acrescentarei comentários e explicações apropriadas.
DKB 28/03

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;
}

0

Você poderia tentar algo assim.

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()

Esta é uma solução terrível para testar a primidez. Depois de encontrar um divisor, você sabe a resposta, mas esse código encontra todos os divisores e decide! E ignora a solicitação do OP para um predicado booleano, como sempre retorna None.
Cdlane 1/10/19

@cdlane eu sei que esta função de retorno boolean não é, eu ainda sou um novato em python e eu sei que ele não é perfeito, obrigado por comentar qualquer maneira
Patrick Jane

0

A maioria das respostas anteriores está correta, mas aqui está mais uma maneira de testar se um número é o número primo. Como atualização, os números primos são números inteiros maiores que 1, cujos únicos fatores são 1 e ele próprio. ( Fonte )

Solução:

Normalmente, você pode criar um loop e começar a testar seu número para ver se é divisível por 1,2,3 ... até o número que você está testando ... etc, mas para reduzir o tempo de verificação, você pode dividir seu número por metade do valor do seu número, porque um número não pode ser exatamente divisível por nada acima da metade dele. Por exemplo, se você deseja ver 100, é um número primo, pode percorrer até 50.

Código atual :

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")  

Você só precisa verificar a raiz quadrada do número, que é um pouco menor que a metade do número. Por exemplo, para n = 100, você só precisa verificar 10, não 50. Por quê? Exatamente na raiz quadrada, os dois fatores são iguais. Para qualquer outro fator, um será menor que sqrt (n) e o outro maior. Portanto, se não tivermos visto um até o momento em que verificamos até o sqrt (n), não o encontraremos depois.
precisa saber é

0

Podemos usar fluxos java para implementar isso em O (sqrt (n)); Considere que noneMatch é um método shortCircuiting que interrompe a operação quando considera desnecessário determinar o resultado:

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

Com a ajuda dos fluxos e lambdas Java-8, ele pode ser implementado desta maneira em apenas algumas linhas:

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

O desempenho deve estar próximo de O (sqrt (N)) . Talvez alguém ache útil.


"range" deve ser substituído por "rangeClosed" para incluir candidatoRoot. Caso candidato <2 também deve ser tratado.
precisa saber é

Como isso difere da resposta anterior de alirezafnatica ?
28619

0

Aqui está a minha opinião sobre a resposta:

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

A função retornará True se alguma das propriedades abaixo for True. Essas propriedades definem matematicamente o que é um primo.

  1. O número é menor ou igual a 3
  2. O número + 1 é divisível por 6
  3. O número - 1 é divisível por 6

>>> isprime(25)retorna True. Você está verificando uma condição necessária muito simples (divisibilidade por 2 ou 3), mas isso não é suficiente .
precisa saber é

Bom, você está correspondendo por esta propriedade: todo número primo maior que 3 tem o formato 6n + 1 ou 6n + 5, mas existem números (como 25) que são do formato 6n + 1 ou 6n + 5, mas eles não são primos
Luis Felipe

0

Quando preciso fazer uma verificação rápida, escrevo esse código simples com base na divisão básica entre números menores que a raiz quadrada da entrada.

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
        return True != n==1

isprime(22783)
  • O último True != n==1é evitar o caso n=1.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.