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;
}
Related
I need to make a program to identify whether the input number is a Smith number or not.
Here is my code:
#include <stdio.h>
void smith(int n) {
int num, sd = 0, sf = 0, i, t, c, j;
num = n;
while (num > 0) {
sd = sd + (num % 10); // Sum of digits of input number
num = num / 10;
}
num = n;
while (num > 1) // To calculate factors of the number
{
for (i = 1; i <= num; i++) {
if (num % i == 0) break;
}
c = 0;
t = i;
for (j = 1; j <= i; j++) // To check if the numbers are prime
{
if (i % j == 0) c++;
}
if (c == 2) {
while (i > 0) {
sf = sf + (i % 10);
i = i / 10;
}
}
num = num / t;
}
if (sd == sf) {
printf("Smith Number");
} else
printf("Not a Smith Number");
}
int main() {
int n;
printf("Enter a number");
scanf("%d", &n);
smith(n);
}
Every time I try to run the code, it just doesn't give an output.
It just takes an input and then probably goes into an infinite loop.
Because the value of t is always 1, num is always stay the same, while loop endlessly. You can fix it like this:
for (i = 2; i <= num; i++) {
if (num % i == 0) break;
}
In
for (i = 1; i <= num; i++) {
if (num % i == 0) break;
}
You always get 1 as factor(every number is divisible by 1) and the only factor you consider is one. As you divide by one, you never get your number smaller. You should start that loop at 2.
The problem is that you are introducing an infinite loop (a very elusive one). Look at these lines of code:
for (i = 1; i <= num; i++) {
if (num % i == 0) break;
}
You are testing if the num is divisible by 1 (which is true for every number), so it will always break, and i will be 1.
Later on, you divide num by this number until num is less than or equal to one, but dividing by one yields the same number, so the loop will never end. If the loop never ends, then your program will stall, hence the program never printing a result.
The solution is simple: start your factoring loop at 2, not 1. Like this:
for (i = 2; i <= num; i++) {
if (num % i == 0) break;
}
1 is a factor of every number, so it is not a useful factor.
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.
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;
}
How can i write a program that lists all sexy prime pairs that exist in n numbers.
For example if n = 10 the output should be (5, 11) and (7, 13)
My idea was to generate all primes within n and then add 6 to each and check if the i + 6 is a prime. But it doesnt work, there's no output and the program ends.
#include <stdio.h>
int main() {
int i, j, n, k, isprime = 1, prime2, flag = 0;
scanf("%d", &n);
for (i = 3; i <= n; i++){
for (j = 2; j <= i; j++){
if (i % j == 0)
break;
}
if (i == j){
prime2 = i + 6;
for (k = 3; k <= prime2; k++){
if (prime2 % k == 0){
flag++;
break;
}
}
if (flag == 0){
printf("%d %d\n", i, prime2);
}
}
}
return 0;
}
Any ideas of what im doing wrong or any tips on how to solve it? (with loops only)
As there're a lot of resources about finding a prime number, I'm not going to discuss that. Rather I'll try to point out the bug in your code.
First problem:
for (k = 3; k <= prime2; k++)
Here you need to run the loop till prime2 - 1. Also you should start checking from 2 rather than 3, just like you did previously. That means,
for (k = 2; k < prime2; k++)
or
for (k = 2; k <= prime2 - 1; k++)
Reason: when k = prime2, prime2 % k will be 0. For finding out whether a number is prime we don't need to check if that number is divisible by 1 and that number itself.
Note: Now you might think why the first prime number loop for (j = 2; j <= i; j++) is working .
It's working because you've given an additional condition if (i == j) after it.
Second problem:
You need to declare the flag variable within the first loop.
for (i = 2; i <= n; i++)
{
int flag = 0;
.... (rest of the code)
....
}
Reason: Basically with the flag value, you're trying to find out whether prime2 is a prime number.
Every time you'll get a prime number from the first loop, you'll have a new value of prime2. In your code, once you're incrementing the value of flag, you're never resetting the flag value.
That's why once your code detects a prime2 which is not a prime, it'll never detect the second prime number again (prime2 which is actually prime).
Overall code:
#include <stdio.h>
int main()
{
int i, j, n, k, isprime = 1, prime2;
scanf("%d", &n);
for (i = 3; i <= n; i++)
{
int flag = 0; // changing point
for (j = 2; j <= i; j++)
{
if (i % j == 0)
break;
}
if (i == j)
{
prime2 = i + 6;
for (k = 2; k < prime2; k++) // changing point
{
if (prime2 % k == 0)
{
flag++;
break;
}
}
if (flag == 0)
{
printf("%d %d\n", i, prime2);
}
}
}
return 0;
}
Few resources to know more about finding out prime numbers:
Prime Numbers
C Program to Check Whether a Number is Prime or not
Sieve of Eratosthenes
You can use Sieve to speed up the program. It can generate all pairs in O(N log N) time. Here's the Algorithm.
Now, you have a boolean array, is_prime where is_prime[i] is true if i is a prime, false otherwise.
Now, iterate from i = 1 to i = N and check if is_prime[i] && is_prime[i + 6], if the condition is true, output the pair.
I really tried but still don't know what's wrong with my code.
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int minus, i, judge;
for (minus = 0, judge = 1; judge == 1; minus++, n -= minus) {
for (i = 2; i * i < n; i++) {
if (n % i == 0)
judge = 1;
else judge = 0;
}
if (judge == 1)
continue;
else break;
}
printf("%d\n", n);
return 0;
}
When I input 143, the output is 143 not 139.
However, when I input 11, the output is the correct answer 11.
The loop test is incorrect: for (i = 2; i * i < n; i++)
If n is the square of a prime number, the loop will stop just before finding the factor.
You should either use i * i <= n or i <= n / i.
Furthermore, you do not enumerate all numbers as you decrement n by an increasing value at each iteration.
Note also that the loop would not find the closest prime to n, but the greatest prime smaller than n, which is not exactly the same thing.
Here is a modified version:
#include <limits.h>
#include <stdio.h>
int isPrime(int n) {
if (n <= 2 || n % 2 == 0)
return n == 2;
for (int i = 3; i <= n / i; i += 2) {
if (n % i == 0)
return 0;
}
return 1;
}
int main() {
int n;
if (scanf("%d", &n) != 1)
return 1;
if (n <= 2) {
printf("2\n");
} else {
for (i = 0;; i++) {
if (isPrime(n - i))
printf("%d\n", n - i);
break;
}
if (n <= INT_MAX - i && isPrime(n + i))
printf("%d\n", n + i);
break;
}
}
}
return 0;
}