Menjana Nombor Perdana di Jawa

1. Pengenalan

Dalam tutorial ini, kami akan menunjukkan pelbagai cara untuk menghasilkan nombor perdana menggunakan Java.

Sekiranya anda ingin memeriksa sama ada nombor utama - berikut adalah panduan ringkas mengenai cara melakukannya.

2. Nombor Perdana

Mari kita mulakan dengan definisi teras. Nombor perdana adalah nombor semula jadi yang lebih besar daripada nombor yang tidak mempunyai pembahagi positif selain satu dan dirinya sendiri.

Sebagai contoh, 7 adalah utama kerana 1 dan 7 adalah satu-satunya faktor bilangan bulat positif, sedangkan 12 bukan kerana mempunyai pembahagi 3 dan 2 sebagai tambahan kepada 1, 4 dan 6.

3. Menjana Nombor Perdana

Di bahagian ini, kita akan melihat bagaimana kita dapat menghasilkan nombor perdana dengan cekap yang lebih rendah daripada nilai yang diberikan.

3.1. Java 7 dan Sebelumnya - Brute Force

public static List primeNumbersBruteForce(int n) { List primeNumbers = new LinkedList(); for (int i = 2; i <= n; i++) { if (isPrimeBruteForce(i)) { primeNumbers.add(i); } } return primeNumbers; } public static boolean isPrimeBruteForce(int number) { for (int i = 2; i < number; i++) { if (number % i == 0) { return false; } } return true; } 

Seperti yang anda lihat, primeNumbersBruteForce melakukan iterasi ke atas nombor dari 2 hingga n dan hanya memanggil kaedah isPrimeBruteForce () untuk memeriksa sama ada nombor itu prima atau tidak.

Kaedah ini memeriksa setiap pembahagi nombor dengan nombor dalam julat dari 2 hingga nombor-1 .

Sekiranya pada satu ketika kita menemui nombor yang boleh dibahagi, kita akan kembali palsu. Pada akhir apabila kita dapati nombor itu tidak dapat dibahagi dengan nombor sebelumnya, kita mengembalikan benar menunjukkan nombor prima.

3.2. Kecekapan dan Pengoptimuman

Algoritma sebelumnya tidak linear dan mempunyai kerumitan masa O (n ^ 2). Algoritma ini juga tidak cekap dan jelas ada ruang untuk diperbaiki.

Mari lihat keadaan dalam kaedah isPrimeBruteForce () .

Apabila nombor bukan bilangan prima, nombor ini boleh difaktorkan menjadi dua faktor iaitu a dan b iaitu nombor = a * b. Sekiranya kedua a dan b lebih besar daripada punca kuasa dua n , a * b akan lebih besar daripada n .

Oleh itu, sekurang-kurangnya satu daripada faktor tersebut mestilah kurang daripada atau sama dengan punca kuasa dua nombor dan untuk memeriksa sama ada nombor adalah bilangan prima, kita hanya perlu menguji faktor yang lebih rendah daripada atau sama dengan punca kuasa dua nombor yang diperiksa.

Nombor perdana tidak boleh menjadi nombor genap kerana nombor genap semuanya boleh dibahagi dengan 2.

Selain itu, nombor perdana tidak boleh menjadi nombor genap kerana nombor genap semuanya boleh dibahagi dengan 2.

Mengingat idea-idea di atas, mari meningkatkan algoritma:

public static List primeNumbersBruteForce(int n) { List primeNumbers = new LinkedList(); if (n >= 2) { primeNumbers.add(2); } for (int i = 3; i <= n; i += 2) { if (isPrimeBruteForce(i)) { primeNumbers.add(i); } } return primeNumbers; } private static boolean isPrimeBruteForce(int number) { for (int i = 2; i*i < number; i++) { if (number % i == 0) { return false; } } return true; } 

3.3. Menggunakan Java 8

Mari lihat bagaimana kita dapat menulis semula penyelesaian sebelumnya menggunakan idiom Java 8:

public static List primeNumbersTill(int n) { return IntStream.rangeClosed(2, n) .filter(x -> isPrime(x)).boxed() .collect(Collectors.toList()); } private static boolean isPrime(int number) { return IntStream.rangeClosed(2, (int) (Math.sqrt(number))) .filter(n -> (n & 0X1) != 0) .allMatch(n -> x % n != 0); } 

3.4. Menggunakan Saringan Eratosthenes

Masih ada kaedah lain yang dapat membantu kita menghasilkan nombor perdana dengan cekap, dan ia dipanggil Sieve Of Eratosthenes. Kecekapan masa adalah O (n logn).

Mari kita lihat langkah algoritma ini:

  1. Buat senarai bilangan bulat berturut-turut dari 2 hingga n : (2, 3, 4,…, n)
  2. Pada mulanya, biarkan p sama dengan 2, nombor perdana pertama
  3. Bermula dari p , hitung dengan kenaikan p dan tandakan setiap nombor ini lebih besar daripada p itu sendiri dalam senarai. Nombor ini akan menjadi 2p, 3p, 4p, dan lain-lain; perhatikan bahawa beberapa dari mereka mungkin sudah ditandakan
  4. Cari nombor pertama lebih besar daripada p dalam senarai yang tidak ditandakan. Sekiranya tidak ada nombor tersebut, hentikan. Jika tidak, biarkan p sekarang sama dengan nombor ini (yang merupakan perdana seterusnya), dan ulangi dari langkah 3

Pada akhir ketika algoritma berakhir, semua nombor dalam senarai yang tidak ditandakan adalah nombor perdana.

Begini kodnya:

public static List sieveOfEratosthenes(int n) { boolean prime[] = new boolean[n + 1]; Arrays.fill(prime, true); for (int p = 2; p * p <= n; p++) { if (prime[p]) { for (int i = p * 2; i <= n; i += p) { prime[i] = false; } } } List primeNumbers = new LinkedList(); for (int i = 2; i <= n; i++) { if (prime[i]) { primeNumbers.add(i); } } return primeNumbers; } 

3.5. Contoh Kerja Saringan Eratosthenes

Mari lihat bagaimana ia berfungsi untuk n = 30.

Pertimbangkan gambar di atas, berikut adalah hantaran yang dibuat oleh algoritma:

  1. Gelung bermula dengan 2, jadi kami meninggalkan 2 tanpa tanda dan menandakan semua pembahagi 2. Ia ditandakan dalam gambar dengan warna merah
  2. Gelung bergerak ke 3, jadi kami meninggalkan 3 tanpa tanda dan menandakan semua pembahagi 3 belum ditandai. Ia ditandakan dalam gambar dengan warna hijau
  3. Gelung bergerak ke 4, sudah ditandai, jadi kami teruskan
  4. Gelung bergerak ke 5, jadi kami membiarkan 5 tidak ditandai dan menandakan semua pembahagi 5 belum ditandai. Ia ditandakan dalam gambar dengan warna ungu
  5. Kami meneruskan langkah di atas sehingga gelung dicapai sama dengan punca kuasa dua n

4. Kesimpulan

Dalam tutorial ringkas ini, kami menggambarkan cara-cara di mana kami dapat menghasilkan nombor perdana sehingga nilai 'N'.

Pelaksanaan contoh-contoh ini boleh didapati di GitHub.