يسرد غربال إراتوستينس جميع الأعداد الأولية حتى الحد الأعلى n شاملًا هذا الحد. تطبع برامج Rust هنا الأعداد الأولية الـ168 التي لا تتجاوز 1000. الحد مشمول؛ و0 و1 ليسا عددين أوليين.
خطوات الغربال وسبب البدء بالمربع
- خصّص
n + 1عنصرًا منطقيًا لاستخدام الفهارس من 0 إلىn. تهيئ النسخة الأساسية العناصر إلى صحيح، ثم تجعل 0 و1 خطأ. إذا كان الحد أقل من 2، تعيد نتيجة فارغة قبل الوصول إلى الفهرس 1. - افحص المرشحين
pبترتيب تصاعدي بدءًا من 2. إذا بقيت العلامة صحيحة، فإنpأولي: اجعل علامات مضاعفاته خطأ بدءًا من \(p^2\) وبخطوة مقدارهاp. لا تشطبpنفسه. - يكفي شطب المضاعفات للمرشحين الذين يحققون \(p^2\le n\)، لأن لكل عدد مؤلف عاملًا أوليًا لا يتجاوز جذره التربيعي.
- في النهاية، افحص الأعداد من 2 إلى
nواطبع كل عدد بقيت علامته صحيحة. نطاق الإخراج لا يقتصر على الجذر التربيعي.
المضاعف \(kp\) الأصغر من \(p^2\)، حيث \(2\le k<p\)، سبق شطبه بواسطة عامل أولي للعدد k أصغر من p. هذا لا يعني أن سرد جميع الأعداد الأصغر قد اكتمل.

الصورة: SKopp، نسخة حدّثها Suricata، Wikimedia Commons، CC BY-SA 3.0. لم يُعدّل الملف. يوضح الرسم الأعداد من 2 إلى 120، بينما تستخدم البرامج أدناه الحد 1000.
التنفيذ الأساسي في Rust
| |
احفظ باسم sieve.rs وترجم باستخدام rustc --edition=2021 sieve.rs -o sieve. في Windows، اجعل اسم الملف التنفيذي sieve.exe. يطبع التشغيل 168 سطرًا، أول عدد فيها 2 وآخرها 997. شُغّلت هذه الأمثلة باستخدام Rust 1.90.0.
تعيد sieve(0) وsieve(1) متجهًا فارغًا، بينما تعيد sieve(2) القيمة [2]. يضمن الشرط p <= n / p حساب p * p فقط عندما لا يتجاوز المربع الحد. وتُفحص المسافة المتبقية قبل إضافة المضاعف التالي. لا حاجة إلى جذر تربيعي باستخدام الفاصلة العائمة.
نسخة تشطب المرشحين الفرديين فقط
الأعداد الزوجية الأكبر من 2 مؤلفة. لذا يمكن جعل علامة 2 صحيحة وتهيئة الأعداد الفردية فقط كمرشحين. مربع العدد الأولي الفردي p فردي أيضًا؛ والانطلاق منه بخطوة \(2p\) يزور المضاعفات الفردية فقط.
| |
احفظ هذه النسخة في ملف آخر وترجمها. تطبع الأعداد الأولية الـ168 نفسها، وتعيد نتيجة فارغة للحدين 0 و1، و[2] للحد 2. لا تجمع دالتي main في ملف واحد.
تتجنب هذه النسخة بعض العمل على الأعداد الزوجية. لكن التهيئة إلى خطأ لا تضمن سرعة أعلى دائمًا. يعتمد الزمن على التهيئة والكتابة والوصول إلى الذاكرة والمترجم والآلة. لا توجد هنا مقارنة لأزمنة مقاسة. تظل المصفوفة مؤلفة من n + 1 عنصرًا كي تقابل الفهارس الأعداد مباشرة.
التعقيد والحدود الممكنة
في نموذج RAM المعتاد، يحتاج الغربال إلى زمن \(O(n\log\log n)\) ومساحة \(O(n)\) للعلامات. هذه تقديرات تقاربية للعمليات والتخزين، وليست أزمنة مقاسة أو تعقيدًا على مستوى البتات لأعداد صحيحة ذات دقة اعتباطية. ويعرض تمرين الغربال في مادة التحليل من Princeton معدل النمو نفسه.
يشغل bool في Rust بايتًا واحدًا، ويخزن Vec<T> العناصر بصورة متجاورة. هذا Vec<bool> ليس مصفوفة بتات مضغوطة. العدد المنطقي للعلامات هو n + 1؛ كما تتطلب بيانات إدارة المتجه والسعة المخصصة والمتجه المعاد Vec<usize> مساحة إضافية.
إذا تعذر تمثيل n + 1، تعيد checked_add القيمة None، ثم يستدعي expect حالة panic. وفي الحالات الأخرى، لا بد من توفر ذاكرة كافية؛ فلا يدعم التنفيذ حدودًا كبيرة كيفما اتفق. للفترات الكبيرة، يمكن النظر في الغربال المجزأ. سرد الأعداد الأولية في نطاق يختلف في غرضه عن اختبار عدد صحيح كبير واحد.
