This is the code to print prime numbers.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
int p;
int i;
int primes[50] = { 0 };
int primeIndex = 2;
bool isPrime;
// hardcode prime numbers
primes[0] = 2;
primes[1] = 3;
for (p = 5; p <= 100; p = p 2) {
isPrime = true;
for (i = 1; isPrime && p / primes[i] >= primes[i]; i)
if (p % primes[i] == 0)
isPrime = false;
if (isPrime == true) {
primes[primeIndex] = p;
primeIndex;
}
}
for (i = 0; i < primeIndex; i)
printf ("%i ", primes[i]);
printf("\n");
return 0;
}
I do not understand a few things in this code:
How does the condition in inner for loop work and what is the use of the isPrime
variable?
CodePudding user response:
The code correctly computes and prints all prime numbers below or equal to 100.
Why is it necessary to hard-code 2 prime numbers (2 and 3)?
2
is a special case: it is the only even prime number. 2
is hard-coded as the first prime number so the outer loops only tests odd numbers.
3
is hard-coded so the outer loop can rely on the array contents for its stop condition p / primes[i] >= primes[i]
. There needs to be at least one odd prime number in the array to avoid an extra test on the array index, such as i < primeIndex
.
As chux commented, the inner loop could start at index i = 0
and then only 2
needs to be hard-coded into the array. The screening process will be slightly less efficient as all numbers will needlessly be tested as divisible by 2, which can be skipped as all numbers tested are known to be odd.
What is the use of boolean expression in the first
for
loop?
The condition test in the first for
loop is p <= 100
. The program enumerates primes below or equal to 100
. The primes
array has a length of 50
which is enough for this range. If the range was much larger, the array size would need to be extended.
The boolean variable isPrime
is used to store the result of the primality test. It is initialized as true
and will be reset to false
if and only if a prime divisor is found in the inner loop.
The variable is tested after the inner loop to check whether p
should be appended to the list of prime numbers.
The condition in the second for
loop isPrime && p / primes[i] >= primes[i]
is an optimisation: it allows the loop to stop as soon as a divisor is found. This test could be simplified as p / primes[i] >= primes[i]
and the loop would continue testing prime divisors up to the square root of p
. Adding break
statement when a divisor is found is an alternative to stop the loop early for more efficiency.
Can someone explain me how the inner for loop works?
The inner loop iterates on prime divisors until one is found to have a 0 remainder (p % primes[i] == 0
) or until the divisor is larger than the square root of p
(p / primes[i] >= primes[i]
).
Note that the array primes
need not be initialized.
Here is a simplified version:
#include <stdio.h>
#include <stdbool.h>
int main() {
int primes[50];
int i, p, primeIndex;
// hardcode 2 prime numbers
primes[0] = 2;
primes[1] = 3;
primeIndex = 2;
// enumerate odd numbers from 5 to 100
for (p = 5; p <= 100; p = p 2) {
// use a boolean variable that will be set to false if p is composite
bool isPrime = true;
// test all odd prime divisors up to the square root of p
for (i = 1; p / primes[i] >= primes[i]; i) {
if (p % primes[i] == 0) {
isPrime = false;
break;
}
}
// if p is prime, add it to the array.
if (isPrime) {
primes[primeIndex ] = p;
}
}
for (i = 0; i < primeIndex; i)
printf("%i ", primes[i]);
printf("\n");
return 0;
}
Here is an even simpler version using a function:
#include <stdio.h>
#include <stdbool.h>
// test if an odd number greater than 3 is a prime
bool isOddPrime(int p, const int *primes) {
for (int i = 1; p / primes[i] >= primes[i]; i) {
if (p % primes[i] == 0)
return false;
}
return true;
}
int main() {
int primes[50] = { 2, 3 }; // hardcode 2 prime numbers
int primeIndex = 2;
for (int p = 5; p <= 100; p = p 2) {
if (isOddPrime(p))
primes[primeIndex ] = p;
}
for (i = 0; i < primeIndex; i)
printf("%i ", primes[i]);
printf("\n");
return 0;
}
CodePudding user response:
It is not unusual to have edge cases hardcoded, especially when there are not many of them. However, rest of the code is not good – I have tried and result is not ok.
Here what you can investigate and try to optimize further on. O(n**2).
int main()
{
int n, i, fact, j;
printf("Enter the upper limit: ");
scanf("%d", &n);
printf("Prime numbers up to the %d are: \n", n);
for( i = 1; i <= n; i )
{
fact = 0;
for ( j = 1; j <= n; j )
{
if( i % j == 0 )
fact ;
}
if ( fact == 2 )
printf("%d ", i);
}
return 0;
}
For example, inner loop test case could be narrowed from j <= n
to j <= n/2
.