This C17 program uses trial division to test numbers and list the primes from 1 through an inclusive upper bound n. A prime is an integer at least 2, so an upper bound of 0 or 1 produces no primes. Enter one decimal integer between 0 and INT_MAX.
Code
| |
Compile and run
Save the program as primes.c. In an environment with GCC, run gcc -std=c17 -Wall -Wextra -O2 primes.c -o primes, then ./primes. Entering 30 prints a heading followed by this line:
| |
An upper bound of 2 prints 2; 0 or 1 prints an empty line. Input is one line of text, limited to 127 bytes excluding its newline. Leading and trailing whitespace and a leading + are allowed. Negative values, empty lines, noninteger text, out-of-range values, overlong lines and read failures cause an error and termination. Only the first line is processed; later lines are unused.
How the test and input handling work
isPrimereturns false for values at most 1 and true for 2 and 3. Other multiples of 2 or 3 return false. It then testsiandi + 2fori = 5, 11, 17, .... These candidates have the forms6k - 1and6k + 1; they are not multiples of 6, and not every number of these forms is prime.- Every composite has a prime divisor at most its square root, so testing while
i <= num / iis sufficient. For positive integers, this covers the same range asi * i <= numwhile avoiding multiplication overflow inint. No floating-point square root is needed. printPrimesprints only an empty line when the bound is below 2. Otherwise, it prints 2 and tests odd candidates. The checki > n - 2exits before incrementing, avoiding overflow in the finali += 2even when the bound isINT_MAX.readLimitreads withfgets, checks the end pointer andERANGEfromstrtol, and verifies the range from 0 throughINT_MAXbefore converting toint. The argument toisspaceis converted tounsigned char. Ignoring the return value ofscanf("%d", &n)risks using an uninitializednafter failed input. A conversion result outside the range ofintcannot simply be assumed to produce a normal conversion failure either.
Scope
INT_MAX depends on the implementation. It is 2,147,483,647 with a 32-bit int, but C does not require that value everywhere. Representing an upper bound does not mean listing all primes up to it will be quick.
This is an implementation for learning trial division. Testing one number uses at most a number of divisions proportional to its square root; listing all candidates has a coarse upper bound of O(n sqrt(n)) divisions. This counts a division as one operation; it is neither bit complexity nor a measured runtime. Consider the sieve of Eratosthenes for listing primes over a large range. This is not a cryptographic prime generator. For testing large integers, see the Miller–Rabin article.
The C input-function and integer-arithmetic rules can be checked in clauses 6.5, 7.4, 7.21.6.2, 7.21.7.2 and 7.22.1.4 of WG14’s C11 committee draft N1570.
