Printing prime numbers using arrays - arrays

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?

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;
}

Related

What is this for loop doing? I don't understand the functionality of the for loop here

This is my code to print all the prime numbers between 1 to 100; I need to use arrays for this and this is important part of the challenge:
#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;
}
For the most part, I do understand the code but I can't understand this part of the code:
for (i = 1; isPrime && p / primes[i] >= primes[i]; ++i)
Particularly, the termination condition of the for loop – isPrime && p / primes[i] >= primes[i]. Can you please help me out here? I am a beginner when it comes to the C language.
isPrime is a flag indicating that the number is potentially prime (ie we do not proved opposite)
p / primes[i] >= primes[i] checks if it makes sense to check if the number is prime for the previously found prime as a divisor
p % primes[i] == 0 checks if the number is not prime - setting the flag from point 1.

Generating prime numbers

I have started learning C language recently, but since I've first stumbled upon prime number generators I've been having trouble understanding the code. to be clear i do know what prime numbers are, i just would like someone to explain to me what happens in the code. here is an example from a book that im studying.
#include <stdio.h>
#include <stdbool.h>
int main(void) {
int p, i, primes[50], primeIndex = 2;
bool isPrime;
primes[0] = 2;
primes[1] = 3;
for (p = 5; p <= 50; p = p + 2) {
isPrime = true;
// this is the part that I'm having trouble with
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've been scratching my head for quite some time by now and i can't get through this one on my own, I would be glad if someone could help.
To determine if p is prime, the loop iterates on the array of primes found so far, checking if p modulo primes[i] is 0, which indicates that p is a multiple of primes[i]. If so isPrime is set to false and the loop stops at the next iteration because the test isPrime && p / primes[i] >= primes[i] will be false.
The reason for the second part of the test, p / primes[i] >= primes[i], is to stop the loop once all prime numbers less or equal to the square root of p have been tested.
Here is an alternate version with a simpler test and a break statement:
isPrime = true;
for (i = 1; p / primes[i] >= primes[i]; ++i) {
if (p % primes[i] == 0) {
isPrime = false;
break;
}
}
// here isPrime is true if and only if p is a prime number.
Note that the primes[] array has been initialized with 2 and 3, so 5 will be proven a prime immediately because 5 / primes[1] = 5 / 3 = 1, which is smaller than 3.
Note also that only even numbers are tested from 5 up and i starts at 1, skipping the modulo operation by 2, which will obviously evaluate to 1.
Finally, p is only tested up to 50, which makes the array of 50 primes amply sufficient: only 23 values are tested in the loop (odd numbers from 5 to 49) so at most 25 values could potentially be set in primes[].
#include <stdio.h>
int main() {
int n, i, flag = 0;
printf("Enter a positive integer: ");
scanf("%d", &n);
for (i = 2; i <= n / 2; ++i) {
if (n % i == 0)
{
flag = 1;
break;
}
}
if (n == 1) {
printf("1 is neither prime nor composite.");
}
else
{
if (flag == 0)
printf("%d is a prime number.", n);
else
printf("%d is not a prime number.", n);
}
return 0;
}

Program to print sum of primes in C

#include <stdio.h>
#include <math.h>
int main() {
int n, count, sum;
printf("Enter upper bound n \n");
scanf("%d", &n);
for (int a = 1; a <= n; a++) {
count = 0;
sum = 0;
for (int i = 2; i <= sqrt(a); ++i) {
if (a % i == 0) {
count++;
break;
}
}
if (count == 0 && a != 1) {
sum = a + sum;
}
}
printf("%d", sum);
}
The program is my attempt to print summation of primes < n. I am getting sum = 0 every time and I am unable to fix this issue.
The reason you do not get the sum of primes is you reset the value of sum to 0 at the beginning of each iteration. sum will be 0 or the value of the n if n happens to be prime.
Note also that you should not use floating point functions in integer computations: i <= sqrt(a) should be changed to i * i <= a.
The test on a != 1 can be removed if you start the loop at a = 2.
Here is a modified version:
#include <stdio.h>
int main() {
int n = 0, sum = 0;
printf("Enter upper bound n: \n");
scanf("%d", &n);
// special case 2
if (n >= 2) {
sum += 2;
}
// only test odd numbers and divisors
for (int a = 3; a <= n; a += 2) {
sum += a;
for (int i = 3; i * i <= a; i += 2) {
if (a % i == 0) {
sum -= a;
break;
}
}
}
printf("%d\n", sum);
return 0;
}
For large values of n, a much more efficient approach would use an array and perform a Sieve of Eratosthenes, a remarkable greek polymath, chief librarian of the Library of Alexandria who was the first to compute the circumference of the earth, 2300 years ago.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int n = 0;
long long sum = 0;
if (argc > 1) {
sscanf(argv[1], "%i", &n);
} else {
printf("Enter upper bound n: \n");
scanf("%i", &n);
}
// special case 2
if (n >= 2) {
sum += 2;
}
unsigned char *p = calloc(n, 1);
for (int a = 3; a * a <= n; a += 2) {
for (int b = a * a; b < n; b += a + a) {
p[b] = 1;
}
}
for (int b = 3; b < n; b += 2) {
sum += p[b] * b;
}
free(p);
printf("%lld\n", sum);
return 0;
}
Error about sum getting set to zero inside the loop has been already pointed out in previous answers
In current form also, your code will not return zero always. It will return zero if value of upper bound is given as non prime number. If prime number is given as upper bound, it will return that number itself as sum.
As mentioned in comment you should initialize sum before first loop something like
int n, count, sum=0;
or you can initialize sum in the loop like
for(a=1,sum=0;a <= n; a++)
and remove sum=0; inside the first loop because it changes sum to 0 every time first loop executes. You can check this by inserting this lines to your code
printf("Before sum %d",sum);
sum = 0;
printf("After Sum %d",sum);
make sure sure that if you are initializing sum in the loop, define "a" in outer of the loop if not the sum goes to local variable to for loop and it hides the outer sum.

How to fix 'time limit exceeded' in some test cases when using the for loop?

We have a series of numbers which is the sum of numbers from 1 to n.(1,3,6,10,...)
The question wants me to find the smallest number in this series which has k divisors.
My code works properly on all test cases but it exceeds the time limits.
It has one while loop and one for loop inside it.
int main()
{
int k, sum, counter = 0, n = 1;
scanf("%d", &k);
while (counter != k) {
counter = 0;
sum = n*(n + 1) / 2; //sum of numbers from 1 to n.(formula)
for (int i = 1; i <= sum / 2; i++) //counts the divisors
if (sum%i == 0)counter++;
counter++; //adds one to the counter because of number 1
n++;
}
printf("%d",sum);
return 0;
}
And here is a example:
Input:k=4
Output:6
What should I do to have a faster and better program?
Did not find a good dup. Here is a solution with O(sqrt(n)) complexity. It's taken from https://www.geeksforgeeks.org/count-divisors-n-on13/
// function to count the divisors
int countDivisors(int n)
{
int cnt = 0;
for (int i = 1; i <= sqrt(n); i++) {
if (n % i == 0) {
// If divisors are equal,
// count only one
if (n / i == i)
cnt++;
else // Otherwise count both
cnt = cnt + 2;
}
}
return cnt;
}
On the same site, there is one that runs in O(n^(1/3)) that is slightly more complex. It's for C++, but just add #include <stdbool.h> and it should work.
void SieveOfEratosthenes(int n, bool prime[],
bool primesquare[], int a[])
{
// Create a boolean array "prime[0..n]" and initialize all entries as
// true. A value in prime[i] will finally be false if i is Not a prime,
// else true.
for (int i = 2; i <= n; i++)
prime[i] = true;
// Create a boolean array "primesquare[0..n*n+1]" and initialize all
// entries it as false. A value in squareprime[i] will finally be true
// if i is square of prime, else false.
for (int i = 0; i <= (n * n + 1); i++)
primesquare[i] = false;
// 1 is not a prime number (Look it up if you doubt it)
prime[1] = false;
for (int p = 2; p * p <= n; p++) {
// If prime[p] is not changed, then it is a prime
if (prime[p] == true) {
// Update all multiples of p
for (int i = p * 2; i <= n; i += p)
prime[i] = false;
}
}
int j = 0;
for (int p = 2; p <= n; p++) {
if (prime[p]) {
// Storing primes in an array
a[j] = p;
// Update value in primesquare[p*p], if p is prime.
primesquare[p * p] = true;
j++;
}
}
}
// Function to count divisors
int countDivisors(int n)
{
// If number is 1, then it will have only 1
// as a factor. So, total factors will be 1.
if (n == 1)
return 1;
bool prime[n + 1], primesquare[n * n + 1];
int a[n]; // for storing primes upto n
// Calling SieveOfEratosthenes to store prime factors of n and to store
// square of prime factors of n
SieveOfEratosthenes(n, prime, primesquare, a);
// ans will contain total number of distinct divisors
int ans = 1;
// Loop for counting factors of n
for (int i = 0;; i++) {
// a[i] is not less than cube root n
if (a[i] * a[i] * a[i] > n)
break;
// Calculating power of a[i] in n.
int cnt = 1; // cnt is power of prime a[i] in n.
while (n % a[i] == 0) // if a[i] is a factor of n
{
n = n / a[i];
cnt = cnt + 1; // incrementing power
}
// Calculating number of divisors. If n = a^p * b^q then total
// divisors of n are (p+1)*(q+1)
ans = ans * cnt;
}
// if a[i] is greater than cube root of n
// First case
if (prime[n])
ans = ans * 2;
// Second case
else if (primesquare[n])
ans = ans * 3;
// Third casse
else if (n != 1)
ans = ans * 4;
return ans; // Total divisors
}
If the above is not enough, you should look into some kind of dynamic programming. Both of the above method is calculating each number from scratch. But if you're going to do it for several numbers, it is quite possible that you can use information from previous numbers. Just to give an idea for how it works, here is an algorithm calculating all primes from 2 to n:
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
// After running this function, prime[n] will be true iff n is a prime
void createPrimeArray(bool *prime, size_t size)
{
prime[0] = prime[1] = false;
for(size_t i=2; i<size; i++)
prime[i] = true;
for(size_t i=2; i<sqrt(size); i++) {
size_t j=i;
while(!prime[j])
j++;
for(size_t k=2*j; k<size; k+=j)
prime[k] = false;
}
}
int main(void)
{
bool prime[200];
createPrimeArray(prime, 200);
for(int i=0; i<200; i++) {
if(prime[i])
printf("%d ", i);
}
}
The above can possibly be optimized further. It's purpose is to show how you can reuse information. After the first run in the second for loop in createPrimeArray we have marked all numbers that are dividable by 2 as non-primes, and thus we don't have to care about those anymore.

Calculating large power of a number in c

I am writing a program in c to store 2^100000, and I am using arrays to store the result.
Here is the full code:
#include <stdio.h>
#include <math.h>
int main()
{
int test, n, i, j, x, resul;
int a[200], m, temp;
scanf("%d", &test);
for (i = 0; i < test; i++) {
a[0] = 3; // initializes array with only 1 digit, the digit 1.
m = 1; // initializes digit counter
scanf("%d", &n);
temp = 0; // Initializes carry variable to 0.
for (i = 1; i < n; i++) {
for (j = 0; j < m; j++) {
x = a[j] * 2 + temp; //x contains the digit by digit product
a[j] = x % 10; //Contains the digit to store in position j
temp = x / 10; //Contains the carry value that will be stored on later indexes
}
while (temp > 0) { //while loop that will store the carry value on array.
a[m] = temp % 10;
temp = temp / 10;
m++; // increments digit counter
}
}
for (i = m - 1; i >= 0; i--) //printing answer
printf("%d", a[i]);
}
return 0;
}
Can some one tell me a more efficient way to do so to reduce the time complexity?
2^n in binary is an (n+1)-digit integer with every bit set to 0 except the most significant bit being set to 1. e.g: 32 = 2^5 = 0b100000
Likewise, 2^100000 can be computed by setting the 100001-th bit in a zeroed 100001 bit long integer to 1. O(1) is as time efficient as you can go.
There are several problems with your code:
The array a is defined with a size of only 200 digits. This is much too small for 2^100000 that has 30103 digits. You should increase the array size and check for overflow in the multiplication algorithm.
You initialize a[0] = 3; and comment this as the digit 1. Indeed you should write a[0] = 1;.
The second loop for (i = 1; i < n; i++) should include the desired power number: you should write for (i = 1; i <= n; i++).
You use the same loop variable for the outer loop and the second level ones, causing incorrect behavior.
You do not test the return value of scanf, causing undefined behavior on invalid input.
You do not check for overflow, invoking undefined behavior on large values.
Here is a corrected version:
#include <stdio.h>
int main()
{
int n, i, j, x, m, test, temp;
int a[32000];
if (scanf("%d", &test) != 1)
return 1;
while (test-- > 0) {
if (scanf("%d", &n) != 1)
break;
a[0] = 1; // initializes array with only 1 digit, the number 1.
m = 1; // initializes digit counter
temp = 0; // Initializes carry variable to 0.
for (i = 1; i <= n; i++) {
for (j = 0; j < m; j++) {
x = a[j] * 2 + temp; //x contains the digit by digit product
a[j] = x % 10; //Contains the digit to store in position j
temp = x / 10; //Contains the carry value that will be stored on later indexes
}
// while loop that will store the carry value on array.
if (temp > 0) {
if (m >= (int)(sizeof(a)/sizeof(*a)))
break;
a[m++] = temp;
temp = 0;
}
}
if (temp > 0) {
printf("overflow");
} else {
for (i = m - 1; i >= 0; i--) //printing answer
putchar('0' + a[i]);
}
printf("\n");
}
return 0;
}
Running this code with input 1 and 100000 on my laptop takes about 6,5 seconds. That's indeed quite inefficient. Using a few optimization techniques that do not really change the complexity of this simple iterative algorithm still can yield a dramatic performance boost, possibly 100 times faster.
Here are some ideas:
store 9 digits per int in the array instead of just 1.
multiply by 2^29 in each iteration instead of just 2, using long long to compute the intermediary result. Initialize the first step to 1 << (n % 29) to account for n not being a multiple of 29. 2^29 is the largest power of 2 less than 10^9.
Here is version that implements these two ideas:
#include <stdio.h>
int main() {
int n, i, j, m, test, temp;
int a[32000];
if (scanf("%d", &test) != 1)
return 1;
while (test-- > 0) {
if (scanf("%d", &n) != 1)
break;
i = n % 29;
n /= 29;
a[0] = 1 << i;
m = 1;
temp = 0;
for (i = 1; i <= n; i++) {
for (j = 0; j < m; j++) {
long long x = a[j] * (1LL << 29) + temp;
a[j] = x % 1000000000;
temp = x / 1000000000;
}
if (temp > 0) {
if (m >= (int)(sizeof(a)/sizeof(*a)))
break;
a[m++] = temp;
temp = 0;
}
}
if (temp > 0) {
printf("overflow");
} else {
printf("%d", a[m - 1]);
for (i = m - 2; i >= 0; i--)
printf("%09d", a[i]);
}
printf("\n");
}
return 0;
}
Running it on the same laptop computes the correct result in only 33ms, that's 200 times faster.
The Time Complexity is the same, but implementation is much more efficient.
Be aware that native C integers are limited, in practice to some power of two related to the word size of your computer (e.g. typically 32 or 64 bits). Read about <stdint.h> and int32_t & int64_t.
Maybe you want some bignums (or bigints), a.k.a. arbitrary precision arithmetic.
The underlying algorithms are very clever (and more efficient than the naive ones you learned in school). So don't try to reinvent them, and use a library like GMPlib

Resources