يستخدم برنامج C17 هذا القسمة التجريبية لاختبار الأعداد وسرد الأعداد الأولية من 1 إلى الحد الأعلى n شاملًا هذا الحد. العدد الأولي عدد صحيح لا يقل عن 2، لذلك لا تظهر أعداد أولية عندما يكون الحد 0 أو 1. أدخل عددًا صحيحًا عشريًا واحدًا من 0 إلى INT_MAX.
الكود
| |
الترجمة البرمجية ومثال التشغيل
احفظ البرنامج باسم primes.c. في بيئة يتوفر فيها GCC، نفّذ gcc -std=c17 -Wall -Wextra -O2 primes.c -o primes ثم ./primes. عند إدخال 30، يظهر عنوان يتبعه السطر التالي:
| |
الحد 2 ينتج 2، أما 0 أو 1 فينتج سطرًا فارغًا. يُقرأ الإدخال كسطر نصي واحد لا يتجاوز 127 بايت، دون احتساب محرف السطر الجديد. تُقبل محارف الفراغ في البداية والنهاية، وكذلك علامة + في البداية. القيم السالبة والأسطر الفارغة والنصوص التي لا تمثل عددًا صحيحًا والقيم خارج النطاق والأسطر الطويلة جدًا وإخفاقات القراءة تؤدي إلى رسالة خطأ وإنهاء البرنامج. يُعالَج السطر الأول فقط، ولا تُستخدم الأسطر اللاحقة.
آلية الاختبار ومعالجة الإدخال
- تعيد
isPrimeالقيمة خطأ للأعداد التي لا تتجاوز 1، وصحيح للعددين 2 و3. وتعيد خطأ لبقية مضاعفات 2 أو 3. ثم تختبرiوi + 2للقيمi = 5, 11, 17, .... القواسم المرشحة من الشكل6k - 1أو6k + 1، وليست مضاعفات 6. وليس كل عدد من هذين الشكلين أوليًا. - لكل عدد مؤلف قاسم أولي لا يتجاوز جذره التربيعي؛ لذا يكفي مواصلة الاختبار ما دام
i <= num / i. للأعداد الصحيحة الموجبة، يغطي هذا الشرط النطاق نفسه الذي يغطيهi * i <= num، مع تجنب تجاوز سعة الضرب في النوعint. ولا حاجة إلى حساب جذر تربيعي باستخدام الفاصلة العائمة. - تطبع
printPrimesسطرًا فارغًا فقط عندما يكون الحد أقل من 2. وإلا تطبع 2 أولًا، ثم تختبر المرشحين الفرديين. إذا تحققi > n - 2، تنتهي الحلقة قبل الجمع، مما يمنع تجاوز السعة في آخرi += 2حتى عندما يكون الحدINT_MAX. - تقرأ
readLimitالإدخال بواسطةfgets، وتفحص مؤشر نهاية التحويل وERANGEالناتجين عنstrtol، ثم تتحقق من أن القيمة ضمن النطاق من 0 إلىINT_MAXقبل تحويلها إلىint. وتحوّل وسيطisspaceأولًا إلىunsigned char. تجاهل القيمة المعادة منscanf("%d", &n)قد يؤدي إلى استخدامnغير مهيأ بعد إخفاق الإدخال. ولا يجوز أيضًا افتراض أن نتيجة تحويل خارج نطاقintستُعامل كمجرد إخفاق عادي في التحويل.
نطاق الاستخدام
تعتمد INT_MAX على التنفيذ. في حالة int ذي 32 بت، تساوي 2,147,483,647، لكن C لا تفرض هذه القيمة على جميع التنفيذات. القدرة على تمثيل حد أعلى لا تعني أن سرد جميع الأعداد الأولية حتى ذلك الحد سيكون سريعًا.
هذا التنفيذ مخصص لتعلّم القسمة التجريبية. عند اختبار عدد واحد، يُحد عدد عمليات القسمة من الأعلى بمقدار يتناسب مع جذره التربيعي. ولسرد جميع المرشحين، يمكن استخدام O(n sqrt(n)) عملية قسمة كحد أعلى تقريبي. تُحسب كل قسمة هنا كعملية واحدة؛ وهذا ليس تعقيدًا على مستوى البتات ولا زمنًا مقاسًا. لسرد الأعداد الأولية في نطاق كبير، يمكن النظر في غربال إراتوستينس. هذا البرنامج ليس مولّدًا للأعداد الأولية لأغراض التشفير. لاختبار أعداد صحيحة كبيرة، انظر مقال ميلر–رابين.
يمكن الرجوع إلى قواعد دوال الإدخال وحساب الأعداد الصحيحة في C ضمن الأقسام 6.5 و7.4 و7.21.6.2 و7.21.7.2 و7.22.1.4 من مسودة لجنة C11 ذات الرقم N1570 من WG14.
