
(
Sumber Gambar )
Telah diketahui bahwa Saringan Eratosthenes (RE) adalah salah satu algoritma tertua yang muncul jauh sebelum penemuan komputer. Oleh karena itu, Anda mungkin berpikir bahwa selama berabad-abad algoritma ini telah dipelajari naik turun dan tidak ada yang dapat ditambahkan ke dalamnya. Jika Anda melihat Wikipedia, ada banyak referensi ke sumber-sumber resmi di mana Anda dapat dengan mudah tenggelam. Karena itu, saya terkejut ketika saya tidak sengaja menemukan bahwa
opsi yang disajikan secara optimal di Wikipedia dapat dioptimalkan secara signifikan.
Seperti itu. Dalam diskusi tentang artikel tentang pemrograman fungsional (FP), ia mengajukan
pertanyaan : bagaimana menulis RE dalam paradigma ini. Memiliki lebih dari pengetahuan FP yang sedikit, saya tidak berani menilai jawabannya, tetapi peserta lain dalam diskusi menolak beberapa solusi yang diajukan segera, menunjukkan bahwa alih-alih kompleksitas teoretis
O(n log logn) (1)implementasi yang diusulkan akan memiliki kompleksitas komputasi
O(n2/ logn) (2)dan dengan kompleksitas seperti itu Anda tidak bisa menunggu ketika, misalnya, 10 juta angka disaring. Saya menjadi tertarik dan saya mencoba untuk mengimplementasikan versi optimal menurut Wikipedia, menggunakan pemrograman prosedural yang biasa. Di Delphi-7, saya mendapat kode berikut:
Listing 1program EratosthenesSieve;
RE diwakili oleh array Boolean saringan dengan nilai terbalik - jika bilangan prima, ini diindikasikan sebagai false, yang mengurangi jumlah operasi negasi (bukan) selama pengayakan. Ada 3 prosedur dalam program: inisialisasi RE - init, perhitungan (pengayakan dan pencabutan angka dalam RE) - kalk, dan pencetakan bilangan prima yang ditemukan sebagai hasil - cetak, dan jumlah angka yang ditemukan dihitung. Saya terutama akan menarik perhatian pada keluaran komentar bilangan prima dalam prosedur cetak: untuk pengujian pada N = 1000, komentar dihapus.
Di sini, di prosedur kalk, saya menggunakan rekomendasi Wikipedia: untuk nomor utama i berikutnya, hapus angka dari RE
i2,i2+i,i2+2i,...
Program ini menembus angka satu miliar dalam 17,6 detik. pada PC saya (3,4 GHz Intel Core i7 CPU).
Setelah membuat program ini, saya tiba-tiba teringat sifat-sifat
nomor genap dan ganjil yang terkenal .
Lemma 1. 1) odd + odd = even; 2) ganjil + genap = ganjil; 3) even + even = even.Bukti1)
(2n+1)+(2m+1)=2n+2m+2 habis dibagi 2. TCD.
2)
(2n+1)+(2m)=2n+2m+1 tidak habis dibagi 2 tanpa sisa. Chtd.
3)
(2n)+(2m)=2n+2m habis dibagi 2. TCD.
Lemma 2. Kuadrat dari angka ganjil adalah angka ganjil.Bukti. (2n+1)2=4n2+4n+1 tidak habis dibagi 2 tanpa sisa. Chtd.
Komentar. Angka prima yang lebih besar dari 2 adalah ganjil.Karena itu, Anda hanya dapat menghapus angka ganjil:
i2,i2+2i,i2+4i,... (3)Tetapi pertama-tama Anda harus mencoret semua angka genap. Ini dilakukan oleh prosedur inisialisasi init yang dimodifikasi.
Listing 2 program EratosthenesSieve;
Program ini bekerja selama 9,9 detik. - Hampir dua kali lebih cepat.
Untuk menilai korespondensi operasi real-time dari program dengan teori, saya menyarankan itu
dt=CβO,
dimana
dt - waktu operasi yang diukur;
C - konstan dengan dimensi waktu;
O - penilaian teoritis.
Dihitung dari sini
C untuk mengevaluasi (1) dan (2). Untuk
N=106 dan kurang
dt mendekati nol. Karena itu, saya membawa data pada program pertama untuk besar
N.Seperti yang kita lihat, perkiraan (1) jauh lebih dekat dengan hasil nyata. Untuk program kedua, gambar serupa diamati. Saya sangat ragu bahwa saya menemukan Amerika menggunakan urutan (3) dan saya akan sangat berterima kasih atas hubungan dengan pekerjaan di mana pendekatan ini diterapkan. Kemungkinan besar, penulis Wikipedia sendiri tenggelam dalam lautan informasi tentang perang elektronik dan melewatkan pekerjaan ini.
PS Untuk algoritma Wikipedia dengan βlinear runtimeβ
lihat