Bagaimana cara membuat pemetaan paling ringkas n → isprime (n) hingga batas N?


152

Secara alami, karena bool isprime(number)akan ada struktur data yang bisa saya tanyakan.
Saya mendefinisikan algoritma terbaik , untuk menjadi algoritma yang menghasilkan struktur data dengan konsumsi memori terendah untuk rentang (1, N], di mana N adalah konstanta.
Hanya contoh dari apa yang saya cari: Saya bisa mewakili setiap bilangan ganjil dengan satu bit misalnya untuk rentang angka yang diberikan (1, 10], dimulai dari 3:1110

Kamus berikut dapat diperas lebih banyak, bukan? Saya bisa menghilangkan kelipatan lima dengan beberapa pekerjaan, tetapi angka yang berakhir dengan 1, 3, 7 atau 9 harus ada di dalam array bit.

Bagaimana saya mengatasi masalah?


3
Permintaan Anda agak kabur. Anda memberikan tanda tangan yang menguji angka tunggal tetapi kemudian meminta struktur data (1, N). Apakah Anda menginginkan algoritma yang menghasilkan kamus <int, bool> atau hanya fungsi satu-shot yang memeriksa apakah satu nomor adalah perdana?
Michael Haren

@Michael Maaf, itu adalah deskripsi terbaik yang bisa saya dapatkan. Apa yang saya cari persis seperti yang Anda katakan: kamus boolean. Saya ingin meminimalkan ruang kamus. Terima kasih :)
AraK

1
Jika itu yang Anda cari, itu sudah ditanyakan: stackoverflow.com/questions/1032427/...
Ben S

14
Anda perlu Meminta NSA
Charles Bretana

Jawaban:


79

Ada banyak cara untuk melakukan tes primality .

Sebenarnya tidak ada struktur data yang bisa Anda tanyakan. Jika Anda memiliki banyak angka untuk diuji, Anda mungkin harus menjalankan tes probabilistik karena angka-angka itu lebih cepat, dan kemudian menindaklanjutinya dengan uji deterministik untuk memastikan angka itu prima.

Anda harus tahu bahwa matematika di belakang algoritma tercepat bukan untuk yang lemah hati.


4
Miller-Rabin adalah tes probabilitas cepat populer untuk memulai.
qwr

214

Algoritma tercepat untuk pengujian prima umum adalah AKS . Artikel Wikipedia menjelaskan panjang lebar dan tautan ke makalah asli.

Jika Anda ingin menemukan angka besar, lihat bilangan prima yang memiliki bentuk khusus seperti bilangan prima Mersenne .

Algoritma yang biasanya saya terapkan (mudah dimengerti dan kode) adalah sebagai berikut (dengan 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

Ini adalah varian dari O(sqrt(N))algoritma klasik . Ia menggunakan fakta bahwa prime (kecuali 2 dan 3) berbentuk 6k - 1atau 6k + 1dan hanya melihat pembagi bentuk ini.

Kadang-kadang, Jika saya benar-benar menginginkan kecepatan dan jangkauannya terbatas , saya menerapkan pseudo-prime test berdasarkan teorema kecil Fermat . Jika saya benar-benar menginginkan lebih banyak kecepatan (yaitu menghindari algoritma O (sqrt (N)) secara bersamaan), saya melakukan precompute false positive (lihat nomor Carmichael ) dan melakukan pencarian biner. Sejauh ini ini adalah tes tercepat yang pernah saya terapkan, satu-satunya kelemahan adalah jangkauannya terbatas.


7
Dua pertanyaan: Bisakah Anda menjelaskan lebih baik apa variabel idan wyang, dan apa yang dimaksud dengan bentuk 6k-1dan 6k+1? Terima kasih atas wawasan Anda dan contoh kode (yang saya coba pahami)
Freedom_Ben

6
@ Freedom_Ben Ini dia, quora.com/...
Alan Dong

6
Bukankah lebih baik untuk menghitung sqrtsatu nkali dan membandingkannya i, daripada menghitung i * isetiap siklus dari loop?
Pedro

3
@Dschoni ... tetapi Anda tidak dapat memasukkan implementasi tercepat di bidang komentar di sini untuk dibagikan dengan kami?
GreenAsJade

3
Gagal untuk nomor 1 :(
Damjan Pavlica

27

Metode terbaik, menurut saya, adalah menggunakan apa yang sudah ada sebelumnya.

Ada daftar Nbilangan prima pertama di internet dengan Nperegangan hingga setidaknya lima puluh juta . Unduh file dan gunakan, itu kemungkinan akan jauh lebih cepat daripada metode lain yang akan Anda buat.

Jika Anda menginginkan algoritma aktual untuk membuat bilangan prima Anda, Wikipedia memiliki segala macam hal bagus tentang bilangan prima di sini , termasuk tautan ke berbagai metode untuk melakukannya, dan pengujian utama di sini , baik metode berbasis probabilitas maupun metode deterministik cepat.

Seharusnya ada upaya bersama untuk menemukan miliar pertama (atau bahkan lebih) bilangan prima dan membuatnya dipublikasikan di internet di suatu tempat sehingga orang dapat berhenti melakukan pekerjaan yang sama ini berulang-ulang dan ... :-)


2
@hamedbh: Menarik. Sudahkah Anda mencoba mengunduh file-file itu? Tampaknya mereka tidak ada.
paxdiablo

Belum, saya khawatir: Saya hanya melihat cepat saat istirahat makan siang. Saya akan menghapus tautan itu seandainya ada sesuatu yang berbahaya tentangnya. Maaf, saya harus memeriksanya dulu.
Hamed

1
Daftar semacam itu memang ada. Saya sudah melihatnya bertahun-tahun yang lalu tetapi tidak pernah peduli untuk mengunduhnya. Yang benar adalah, mereka mengambil banyak ruang (relatif berbicara), dan tidak boleh dimasukkan dalam program yang dijual atau didistribusikan. Lebih jauh lagi, mereka akan selalu dan selamanya tidak lengkap. Agak masuk akal untuk menguji setiap angka yang muncul dalam praktik selama penggunaan program, karena jauh lebih sedikit akan diuji dengan cara itu daripada panjang daftar yang Anda miliki. Juga, saya pikir pax tidak menyadari tujuan dari algoritma utama, sebagian besar waktu, adalah untuk menguji efisiensi / kecepatan daripada benar-benar menemukan bilangan prima.
CogitoErgoCogitoSum

2
@CogitoErgoCogitoSum, setuju bahwa daftar semua bilangan prima akan selalu ketinggalan zaman karena saya telah melihat bukti matematika bahwa mereka jumlahnya tak terbatas. Namun, daftar xbilangan prima pertama tidak akan lengkap setelah dibangun :-)
paxdiablo

1
Benar, tetapi ada metode penyimpanan yang lebih baik daripada membaca dari file secara linear. Jika Anda benar - benar ingin membaca dari set prima yang dihasilkan sebelumnya, coba struktur data yang lebih rumit yang mempercepat masalah.
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;
}

ini hanya implementasi c ++ dari algoritma AKS di atas


1
Ini salah satu algoritma deterministik paling efisien yang pernah saya temui, ya, tetapi ini bukan implementasi AKS. Sistem AKS jauh lebih baru daripada algoritma yang diuraikan. Ini bisa dibilang lebih efisien, tetapi agak sulit untuk diterapkan, karena, dari faktorial / koefisien binomial yang berpotensi besar secara astronomis.
CogitoErgoCogitoSum

Bagaimana hal ini berbeda dengan jawaban Derri Leahi (selain ) (selain C bukan Java)? Bagaimana jawaban ini What is the algorithm that produces a data structure with lowest memory consumption for the range (1, N]?
greybeard

1
Bagaimana (n% i == 0 || n% (i + 2) == 0) sesuai dengan 6n + 1 & 6n-1?
yesh

@YeshwanthVenkatesh: How does (n%i == 0 || n%(i+2) == 0) correspond to 6n+1 & 6n-1?bagian dari jawabannya adalah peran yang berbeda n, yang lainnya adalah 6n + 1 & 6n-1 setara dengan (6n-1) +0 & (6n-1) + 2 *.
greybeard

Perhatikan juga bahwa algoritma ini tidak memberikan hasil yang benar untuk 5dan 7.
Athan Clark

7

Saya membandingkan efisiensi saran paling populer untuk menentukan apakah suatu bilangan prima. Aku digunakan python 3.6pada ubuntu 17.10; Saya menguji dengan angka hingga 100.000 (Anda dapat menguji dengan angka yang lebih besar menggunakan kode saya di bawah).

Plot pertama ini membandingkan fungsi (yang dijelaskan lebih jauh dalam jawaban saya), menunjukkan bahwa fungsi terakhir tidak tumbuh secepat yang pertama ketika menambah angka.

plot1

Dan dalam plot kedua kita dapat melihat bahwa dalam kasus bilangan prima waktu tumbuh dengan mantap, tetapi bilangan non-prima tidak tumbuh begitu cepat dalam waktu (karena sebagian besar dari mereka dapat dihilangkan sejak awal).

plot2

Berikut adalah fungsi yang saya gunakan:

  1. jawaban ini dan jawaban ini menyarankan konstruk menggunakan all():

    def is_prime_1(n):
        return n > 1 and all(n % i for i in range(2, int(math.sqrt(n)) + 1))
    
  2. Jawaban ini menggunakan semacam loop sementara:

    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. Jawaban ini termasuk versi dengan 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. Dan saya mencampurkan beberapa ide dari jawaban yang lain menjadi yang baru:

    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
    

Berikut ini skrip saya untuk membandingkan variannya:

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

Menjalankan fungsi compare_functions(n=10**5)(angka hingga 100.000) Saya mendapatkan output ini:

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

Kemudian, jalankan fungsinya compare_functions(n=10**6) (angka hingga 1.000.000) saya mendapatkan output ini:

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

Saya menggunakan skrip berikut untuk memplot hasil:

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

Satu dapat menggunakan sympy .

import sympy

sympy.ntheory.primetest.isprime(33393939393929292929292911111111)

True

Dari sympy docs. Langkah pertama adalah mencari faktor sepele, yang jika ditemukan memungkinkan pengembalian cepat. Selanjutnya, jika ayakan cukup besar, gunakan pencarian membagi dua pada ayakan. Untuk jumlah kecil, serangkaian uji Miller-Rabin deterministik dilakukan dengan basis yang diketahui tidak memiliki sampel tandingan dalam jangkauannya. Akhirnya jika jumlahnya lebih besar dari 2 ^ 64, tes BPSW yang kuat dilakukan. Meskipun ini adalah ujian utama yang mungkin dan kami percaya contoh tandingan ada, tidak ada contoh tandingan yang diketahui


Algoritma adalah urutan langkah-langkah yang didefinisikan dengan baik yang mendefinisikan solusi abstrak untuk suatu masalah. - apa urutan langkah-langkah dalam kode yang disajikan? Apa yang memory consumption?
greybeard

2
@orangtua. Dari sympy docs. Langkah pertama adalah mencari faktor sepele, yang jika ditemukan memungkinkan pengembalian cepat. Selanjutnya, jika ayakan cukup besar, gunakan pencarian membagi dua pada ayakan. Untuk jumlah kecil, serangkaian uji Miller-Rabin deterministik dilakukan dengan basis yang diketahui tidak memiliki sampel tandingan dalam jangkauannya. Akhirnya jika jumlahnya lebih besar dari 2 ^ 64, tes BPSW yang kuat dilakukan. Meskipun ini adalah ujian utama yang mungkin dan kami percaya contoh tandingan ada, tidak ada contoh tandingan yang diketahui.
LetzerWille

6

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

Penjelasan: Angka prima adalah angka yang hanya dapat dibagi dengan sendirinya dan 1. Contoh: 2,3,5,7 ...

1) jika a <2: jika "a" kurang dari 2 itu bukan bilangan prima.

2) elif a! = 2 dan% 2 == 0: jika "a" habis dibagi 2 maka jelas bukan yang utama. Tetapi jika a = 2 kita tidak ingin mengevaluasi itu karena itu adalah bilangan prima. Karenanya kondisi a! = 2

3) return all (a% i for i in range (3, int (a 0,5) +1)): ** Pertama-tama lihat apa yang dilakukan semua perintah () dengan python. Mulai dari 3 kita membagi "a" hingga akar kuadratnya (a ** 0,5). Jika "a" habis dibagi, outputnya akan False. Mengapa akar kuadrat? Katakanlah a = 16. Akar kuadrat dari 16 = 4. Kita tidak perlu mengevaluasi sampai 15. Kita hanya perlu memeriksa sampai 4 untuk mengatakan bahwa itu bukan bilangan prima.

Extra: Loop untuk menemukan semua bilangan prima dalam rentang.

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

1
Apa bedanya dengan jawaban Oleksandr Shmyheliuk ? (Keduanya ketinggalan "langkah 2" di range()...)
greybeard

1
Jika angka genap maka itu bukan bilangan prima (tidak termasuk 2). Jadi tidak perlu memeriksa nomor genap. Ini akan jauh lebih cepat jika Anda ingin mendapatkan bilangan prima dalam kisaran. Ini akan langsung mengecualikan angka genap.
Pertumbuhan mendalam


3

Untuk jumlah yang besar, Anda tidak dapat dengan mudah mengecek apakah nomor kandidat N dapat dibagi dengan tidak ada angka yang kurang dari sqrt (N). Ada banyak tes terukur yang tersedia, seperti tes primality Miller-Rabin . Di bawah ini Anda memiliki implementasi dalam 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

Anda dapat menggunakannya untuk menemukan bilangan prima yang sangat besar:

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

# 10000000000000000000000000000000000000000000000000000000000000000000000000133 is a prime!

Jika Anda menguji bilangan bulat acak, mungkin Anda ingin terlebih dahulu menguji apakah nomor kandidat dapat dibagi oleh salah satu bilangan prima lebih kecil dari, katakanlah 1000, sebelum Anda memanggil Miller-Rabin. Ini akan membantu Anda memfilter non-prima yang jelas seperti 10444344345.


Ini adalah tes Miller. Tes Miller-Rabin adalah versi probabilistik di mana basis yang dipilih secara acak diuji sampai kepercayaan yang cukup tercapai. Juga, tes Miller tidak tergantung pada Hipotesis Riemann secara langsung, tetapi Hipotesis Riemann Generalized (GRH) untuk karakter Diriclet kuadratik (saya tahu ini suap, dan saya juga tidak memahaminya). Yang berarti bukti potensial untuk Hipotesis Riemann bahkan mungkin tidak berlaku untuk GRH, dan karenanya tidak membuktikan uji Miller benar. Kasus yang lebih buruk tentu saja jika GRH dibantah.
Arne Vogel

2

Terlalu terlambat ke pesta, tapi harap ini bisa membantu. Ini relevan jika Anda mencari bilangan prima besar:

Untuk menguji angka ganjil yang besar, Anda perlu menggunakan tes Fermat dan / atau Miller-Rabin.

Tes-tes ini menggunakan eksponensial modular yang cukup mahal, untuk nbit eksponensial Anda memerlukan setidaknya nperkalian nint besar dan divisi int besar. Yang berarti kompleksitas eksponensial modular adalah O (n³).

Jadi sebelum menggunakan senjata besar, Anda perlu melakukan beberapa divisi percobaan. Tapi jangan lakukan dengan naif, ada cara untuk melakukannya dengan cepat. Pertama, kalikan bilangan prima bersama-sama sesuai dengan kata-kata yang Anda gunakan untuk bilangan bulat besar. Jika Anda menggunakan 32 bit kata, kalikan 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 = 3234846615 dan hitung pembagi umum terbesar dengan angka yang Anda uji menggunakan algoritma Euclidean. Setelah langkah pertama jumlahnya dikurangi di bawah ukuran kata dan melanjutkan algoritma tanpa melakukan pembagian bilangan bulat besar lengkap. Jika GCD! = 1, itu berarti salah satu bilangan prima yang Anda kalikan bersama membagi bilangannya, jadi Anda punya bukti bahwa itu bukan bilangan prima. Kemudian lanjutkan dengan 31 * 37 * 41 * 43 * 47 = 95041567, dan seterusnya.

Setelah Anda menguji beberapa ratus (atau ribuan) bilangan prima dengan cara ini, Anda dapat melakukan 40 putaran tes Miller-Rabin untuk mengonfirmasi bahwa bilangan prima, setelah 40 ronde Anda dapat yakin bahwa bilangan tersebut bilangan prima hanya ada 2 ^ -80 peluangnya tidak (itu kemungkinan kerusakan perangkat keras Anda ...).


1

Saya telah mendapatkan fungsi utama yang berfungsi hingga (2 ^ 61) -1 Di sini:

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

Penjelasan:

The all()fungsi dapat didefinisikan ulang dengan ini:

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

The all()Fungsi hanya berjalan melalui serangkaian bools / angka dan kembali Falsejika melihat 0 atauFalse .

The sqrt()fungsi hanya melakukan akar kuadrat dari angka.

Sebagai contoh:

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

Bagian num % xmengembalikan sisanya num / x.

Akhirnya, range(2, int(sqrt(num)))berarti ia akan membuat daftar yang dimulai dari 2 dan berakhir padaint(sqrt(num)+1)

Untuk informasi lebih lanjut tentang jangkauan, lihat situs web ini !

Bagian num > 1ini hanya memeriksa apakah variabel numlebih besar dari 1, karena 1 dan 0 tidak dianggap bilangan prima.

Saya harap ini membantu :)


Tolong berdebat bagaimana ini adalah the bestalgoritma, atau bahkan yang bagus .
greybeard

@greybeard, Sebagian besar fungsi utama di sini tidak naik ke (2 ^ 31) -1 atau terlalu lama untuk angka tinggi, tetapi fungsi saya berfungsi hingga (2 ^ 61) -1, sehingga Anda dapat memeriksa apakah suatu bilangan prima dengan yang lebih luas rentang angka.
WhyAreYouReading

1

Dengan Python:

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

Konversi yang lebih langsung dari formalisme matematika ke Python akan menggunakan semua (n% p! = 0 ...) , tetapi itu memerlukan evaluasi ketat semua nilai p. Versi tidak apa pun dapat berakhir lebih awal jika nilai True ditemukan.


Wrt "semua (n% p! = 0 ...), tetapi itu memerlukan evaluasi ketat semua nilai p" - itu tidak benar. anydan allkeduanya akan keluar lebih awal . Jadi pada saat pertama pdi mana n % padalah 0, allakan keluar.
aneroid

1

algoritma terbaik untuk javascript bilangan Primes

 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

Bilangan prima adalah angka yang hanya dapat dibagi oleh 1 dan itu sendiri. Semua angka lain disebut komposit .

Cara paling sederhana untuk menemukan bilangan prima adalah dengan memeriksa apakah bilangan input adalah bilangan komposit:

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

Program harus membagi nilai numberdengan seluruh angka dari 1 dan hingga nilainya. Jika angka ini dapat dibagi secara merata, tidak hanya dengan satu dan itu sendiri, itu adalah angka gabungan.

Nilai awal variabel iharus 2 karena bilangan prima dan gabungan dapat dibagi secara merata dengan 1.

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

Maka ikurang darinumber karena alasan yang sama. Baik bilangan prima dan gabungan dapat dibagi secara merata. Karena itu tidak ada alasan untuk memeriksanya.

Kemudian kami memeriksa apakah variabel dapat dibagi secara merata dengan menggunakan operator sisanya.

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

Jika sisanya nol, itu artinya number dapat dibagi secara merata, sehingga menjadi bilangan komposit dan mengembalikan false.

Jika nomor yang dimasukkan tidak memenuhi syarat, itu berarti itu adalah bilangan prima dan fungsi mengembalikan true.


1
(Sementara saya pikir simplestsatu interpretasi yang valid dari yang terbaik :) Pertanyaannya adalah Apa algoritma terbaik untuk memeriksa apakah suatu bilangan prima? : Apakah memeriksa pembagian yang number / 2 < i < numbermenguntungkan? Bagaimana dengan number < i*i? Apa yang dapat dimengerti dari jawaban 3³ lainnya?
greybeard

1

Izinkan saya menyarankan Anda solusi sempurna untuk integer 64 bit. Maaf menggunakan C #. Anda belum menetapkannya sebagai python di posting pertama Anda. Saya harap Anda dapat menemukan fungsi modPow sederhana dan menganalisisnya dengan mudah.

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

untuk nomor apa pun, iterasi minimum untuk memeriksa apakah nomor tersebut prima atau tidak dapat dari 2 hingga kuadrat dari angka tersebut. Untuk mengurangi iterasi, bahkan lebih, kita dapat memeriksa apakah jumlahnya dapat dibagi 2 atau 3 karena angka maksimum dapat dihilangkan dengan memeriksa apakah jumlahnya dapat dibagi 2 atau 3. Selanjutnya setiap bilangan prima lebih besar dari 3 dapat dinyatakan sebagai 6 k +1 atau 6k-1. Jadi iterasi dapat berubah dari 6k +1 ke akar kuadrat dari angka tersebut.


1
Akan lebih baik jika Anda menambahkan beberapa penjelasan untuk jawaban Anda menggunakan sunting . Mungkin tidak jelas bagi banyak pembaca mengapa jawaban Anda bagus, dan mereka bisa belajar dari Anda jika Anda menjelaskan lebih lanjut.
Brian Tompsett - 汤 莱恩

0

Memori terkecil? Ini bukan terkecil, tetapi merupakan langkah ke arah yang benar.

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

Tentu saja, Anda harus menentukan definisi CheckPrimality.


0

Saya pikir salah satu yang tercepat adalah metode yang saya buat.

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
kesalahan mungkin ... 6 - i?
Hmmm

0

Gagasan serupa dengan algoritma AKS yang telah disebutkan

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
Tidak ada kaitannya dengan algoritma AKS .
greybeard

Dalam for loop Anda tidak perlu memeriksa "i <= limit", itu sudah cukup untuk memeriksa "i <limit". Jadi dalam setiap iterasi Anda membuat satu perbandingan lebih sedikit.
Andrushenko Alexander

0

Untuk menemukan apakah angka atau angka dalam suatu rentang adalah prima.

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

Jalankan kode ini, ini akan berfungsi untuk daftar dan nomor tertentu
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
Ketika Anda menulis jawaban, meskipun itu benar, harap juga menulis sedikit menjelaskan apa yang Anda lakukan, dan mengapa. Dengan cara ini orang yang membaca jawaban Anda dapat memahami dengan mudah apa yang telah Anda pecahkan. Terima kasih!
kim

1
Tentu Kim, terima kasih telah menunjukkan itu. Ini adalah program pertama saya di Stackoverflow untuk selanjutnya saya akan menambahkan komentar dan penjelasan yang sesuai.
DKB

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

Anda dapat mencoba sesuatu seperti ini.

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

Ini adalah solusi yang mengerikan untuk menguji kesombongan. Setelah Anda menemukan satu pembagi, Anda tahu jawabannya, tetapi kode ini menemukan semua pembagi dan kemudian memutuskan! Dan itu mengabaikan permintaan OP untuk predikat boolean karena selalu kembali None.
cdlane

@cdlane saya tahu ini bukan fungsi pengembalian boolean, saya masih pemula dalam python dan saya tahu itu tidak sempurna, terima kasih sudah berkomentar
Patrick Jane

0

Sebagian besar jawaban sebelumnya benar tetapi di sini ada satu lagi cara untuk menguji untuk melihat nomor adalah bilangan prima. Sebagai penyegaran, bilangan prima adalah bilangan bulat lebih besar dari 1 yang faktor-faktornya hanya 1 dan itu sendiri. ( Sumber )

Larutan:

Biasanya Anda dapat membuat lingkaran dan mulai menguji nomor Anda untuk melihat apakah itu dapat dibagi 1,2,3 ... hingga jumlah yang Anda uji ... dll tetapi untuk mengurangi waktu untuk memeriksa, Anda dapat membagi nomor Anda dengan setengah dari nilai nomor Anda karena angka tidak dapat benar-benar habis dibagi oleh apa pun di atas setengah dari nilainya. Contoh jika Anda ingin melihat 100 adalah bilangan prima, Anda dapat mengulang hingga 50.

Kode aktual :

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

Anda hanya perlu memeriksa ke akar kuadrat dari angka tersebut, yang sedikit lebih kecil dari setengah jumlahnya. Misalnya untuk n = 100 Anda hanya perlu memeriksa ke 10, bukan 50. Mengapa? Tepat pada akar kuadrat, kedua faktor itu sama. Untuk faktor lain mana pun akan lebih kecil dari sqrt (n) dan lainnya lebih besar. Jadi, jika kita belum melihatnya pada saat kita melakukan pemeriksaan hingga dan termasuk sqrt (n), kita tidak akan menemukannya setelah.
DanaJ

0

Kita bisa menggunakan aliran java untuk mengimplementasikan ini di O (sqrt (n)); Pertimbangkan noneMatch adalah metode shortCircuiting yang menghentikan operasi ketika merasa tidak perlu untuk menentukan hasilnya:

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

Dengan bantuan aliran Java-8 dan lambdas, ini dapat diimplementasikan seperti ini hanya dalam beberapa baris:

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

Kinerja harus dekat dengan O (sqrt (N)) . Mungkin seseorang menganggapnya berguna.


"range" harus diganti dengan "rangeClosed" untuk memasukkan kandidatRoot. Calon <2 kasus juga harus ditangani.
udalmik

Bagaimana ini berbeda dari jawaban sebelumnya alirezafnatica ?
greybeard

0

Inilah jawaban saya:

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

Fungsi ini akan mengembalikan True jika salah satu properti di bawah ini adalah True. Properti-properti tersebut secara matematis mendefinisikan apa yang utama.

  1. Jumlahnya kurang dari atau sama dengan 3
  2. Angka +1 dapat dibagi dengan 6
  3. Angka - 1 habis dibagi 6

>>> isprime(25)kembali True. Anda memeriksa kondisi yang diperlukan yang sangat sederhana (dapat dibagi 2 atau 3) tetapi ini tidak cukup .
DanaJ

Bagus, Anda cocok dengan properti ini: setiap bilangan prima lebih besar dari 3 adalah dalam bentuk 6n + 1 atau 6n + 5, tetapi ada nomor (seperti 25) yang berbentuk 6n + 1 atau 6n + 5, tetapi mereka tidak prima
Luis Felipe

0

Ketika saya harus melakukan verifikasi cepat, saya menulis kode sederhana ini berdasarkan pembagian dasar antara angka-angka yang lebih rendah dari input akar kuadrat.

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)
  • Yang terakhir True != n==1adalah untuk menghindari kasus ini n=1.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.