Prime Number program - c

I want to make a program in C language which will take the user input and I would not be able to understand the logic of the loop.
for ( c = 2 ; c <= n - 1 ; c++ )
The program code is given below:-
#include<stdio.h>
#include<conio.h>
void main()
{
int n, c;
printf("Enter a number to check if it is prime\n");
scanf("%d", &n);
for ( c = 2 ; c <= n - 1 ; c++ )
{
if ( n % c == 0 )
{
printf("%d is not prime.\n", n);
break;
}
}
if ( c == n )
printf("%d is prime.\n", n);
getch();
}
I have used the for loop which will end up the statement of n - 1 in for loop. If I will give the input 11 then it will end up on 11 - 1 = 10 then how it will give up the logic of if(c == n) { printf("%d", n);?

If I will give the input 11 then it will end up on 11 - 1 = 10 then how it will give up the logic of if(c == n) { printf("%d", n);?
Now correctly understand your for loop condition:
for ( c = 2 ; c <= n - 1 ; c++ )
^^^^^^^^^^^^
2 <= 11 - 1 -> True // {for block executes }
3 <= 11 - 1 -> True // {for block executes }
:
:
9 <= 11 - 1 -> True // {for block executes }
10 <= 11 - 1 -> True // {for block executes }
11 <= 11 - 1 -> False breaks //{And Now for block NOT executes}
if (c == n)
^^^^^^
11 == 11 -> True // {if block executes}
According to for loop condition c <= n - 1, loop breaks when c value becomes equals to n. So if n is equals to 11 loop condition is true for c = 2 to c = 10, in each iteration c increments by one (using c++ increment) when c becomes 11 (ot say n) then condition c <= n - 1 become false and loop breaks.
In if condition (after for loop) c value compared with n. that is:
if ( c == n )
// 11 == 11 that is true
for n = 11 it becomes and c = 11 if condition evaluates true and printf() associated with if executes.
It is also important to understand that the for-loop only terminates for c = n when n is a prime number, but if suppose n is a non-prime number then for-loop will break for c value less then n - 1 due to break; statement in nested if block in for-loop.
for( c = 2; c <= n - 1; c++ )
{
if(n % c == 0)<=="for Non-prime `n`, if condition will be true for some `c < n - 1`"
{ ^^^^^^^^^^^ True
printf("%d is not prime.\n", n);
break; <== "move control outside for-loop"
} // |
} // |
// <---------+ // if break; executes control moves here with c < n - 1
if (c == n)<== "this condition will evaluates FALSE"
^^^^^^^^ False
For example if n = 8 then in very first iteration of for-loop with value c = 2 if condition if(n % c == 0) that evaluates as if(8 % 2 == 0) == if( 0 == 0) = True and break; statement inside if-block moves control outside for-loop(as shown in figure).
Because this time for loop not terminated due to c <= n - 1 condition but braked because of if(n % c == 0) so out-side for-loop c value is less than n hence if (c == n) evaluates as False.

The for loop loops from c = 2 to c = n - 1 except it hit's the break statement. If it does, it will jump out of the loop. If you never break then your c will actually be n after the loop.
And here is why. The loop works like this:
initialize the for loop with c = 2
Check for condition (c <= n - 1)
if true: execute loop body
if false: jump past loop
increment c by one
goto 2.
Example: Suppose your n is 3.
we set c to 2, now c == 2 and n == 3
2 <= 3 - 1 is true, so the loop body will be executed
we increment c by 1, now c == 3 and n == 3
we go back to 2. in the description
3 <= 3 - 1 is false, so we don't execute the loop body now and jump out of the loop
after we left the loop c == 3 and n == 3 so c == n
So if we never hit the break statement c will be equal to n after the loop. We hit the break statement if n is not prime. If we break c will miss at least one increment and thus c < n after the loop. Now c == n will evaluate to false and the if statements body of if ( c == n ) will not be executed.
Now to the if ( n%c == 0 ). n%cmeans n modulo c, so the remainder of the division of n by c. If this remainder is 0 then c is an integer divisor of n. So in the loop you are testing n for any divisor bigger than 1 and smaller than n.
If there is a divisor of n except 1 and itself, n can't be prime. So if you hit any c with 1 < c < n that makes n%cequal to 0 n can't be prime.
Hint: You don't have to test for divisors bigger than √n.

Your assumption that c ends up being n - 1 is incorrect. If you step through your program with the debugger you should see that for n == 11, c == 11 at the end of the loop.
If we don't break early then the last time the loop body executes is indeed when c == n - 1 however c is then incremented and the loop invariant test fails so after the loop c == n.

Consider what it means when you say that a number is prime.
A number p is prime when for every n>1, n<p, the remainder r = 0 for p/n = r.
So, this loop runs through each value (c) the range [2..p-1], testing for the remainder.
int isprime = 1; //use a flag to indicate prime, assume prime until proven otherwise
for ( c = 2 ; //initialize c=2, the first value in the range [2..p-1]
c <= n - 1 ; //check whether c is still in the range [2..p-1]
c++ ) //increment c to the next value in the range [2..p-1]
{
if ( n % c == 0 ) //modulo '%' is the remainder of the integer division
{
isprime = 0;
break;
}
}
printf("%d %s prime.\n", n, isprime?"is":"is not");
Rather than test that the number is prime by checking a side effect of the loop counter, why not set a flag before the loop, and then test it as the decision for prime at the end? The result is code that is less fragile, error-prone, and clearer.
Want to save about half the work? Once you test n%2, we know that there is no number k such that k*2=n, right? so check the range [2..p/2], and change your loop to,
for( c = 2; c <= n/2; c++ )
Can you think of a number smaller than n/2 that works?
An interesting algorithm for finding multiple primes is the Sieve of Erastosthenes.

Related

C program stops on certain number [duplicate]

This question already has answers here:
Project Euler Question 14 (Collatz Problem)
(8 answers)
Closed 1 year ago.
Hi I am new to C and I chose a project to get better
I wanted to make a program that would brute force every number if it is according to Collatz conjecture.
Collatz conjecture:
For those who do not know what Collatz conjecture is click here
Summary:
If a number is odd it is multiplied by 3 and increased by 1
If even it is divided by 2
This is repeated until it reaches 1
My code:
#include <stdio.h>
int main(){
int n, x, a, b;
n = 5; //number we check first (has to be bigger than 4 because 4,3,2,1 is a loop)
//n is later on a number that is currently being tested
//all numbers smaller than 2 ** 64 were brute force tested and are according to Collatz's conjecture
x = n; //x begins as n and then changes according to rules of cenjecture until it reaches 1
a = 1; //a is set to 1 until x = 1 which means that number n is according to conjecture
b = 1; //creates an infinite loop
while(b == 1){ //runs forever
if(a == 1){
if(x == 1){
a = 0; //if x reaches 1 (number n is according to conjecture) a is set to 0 and n is increased by 1 ===
} // ||
else{ // ||
if(x % 2 == 0){ // ||
x = x / 2; // ||
} // ||
else{ // ||
x = x * 3 + 1; // ||
} // ||
} // ||
} // ||
else{ // ||
printf("%d \n", n); // ||
n = n + 1; // <<<<<============================================================================
x = n; //
a = 1; //
}
}
}
Problem:
The problem is that when I run it it stops on number 113383 and has problems with it. I even let it run for more than 5 minutes but it did not do anything. I even tried to run the same number in my python program which test input number and it had it in no time.
I tried to start with n = 113384 and it worked and stopped again on 134378.
Is number 113383 anyhow different in C or is there a flaw in my code.
Please help if you can.
Thank you very much
Try declaring the variable as a "long int" this could be due to the maximum size of an int witch is –32,767 to 32,767

Regarding if else statements in C language

Please explain to me why this code is wrong for the task and below I have explained all the four conditions -[][1]
#include stdio.h
int main()
{
int n;
scanf ("%d", &n); //taking input
if (n / 2 != 0)
{
printf ("Weird"); //checking first condition
}
else if (n % 2 == 0 && 2 <= n <= 5)
{ //checking second condition
printf ("Not Weird");
}
else if (n % 2 == 0 && 6 <= n <= 20)
{ //checking third condition
printf ("Weird");
}
else if (n % 2 == 0 && n > 20)
{ //checking fourth condition
printf ("Not Weird");
}
else
{
printf ("Error");
}
return 0;
}
this is the image for the question[1]: https://i.stack.imgur.com/OtY7o.png**
Testing for Odd or Even
n / 2 != 0 does not test whether n is odd. n/2 calculates the quotient that results from dividing n by 2 (rounding any fraction down). So 0/2 is 0, 1/2 is 0, 2/2 is 1, 3/2 is 1, 4/2 is 2, and so on. So n / 2 != 0 is true for all n other than −1, 0, and 1.
To test whether a number is odd, you can use n % 2 != 0. n%2 calculates the remainder from the division. If it is zero, n is even. If n is not zero, n is odd.
Using Else Efficiently
Once you have tested whether n is odd using n % 2 != 0, you do not have to test whether it is even in the else clauses. The else expressions and their statements will be evaluated only if the if expression is false, which happens (after the correction above) only when n is even. So we do not need to test again.
Testing For an Interval
In C, 2 <= n <= 5 does not test whether n is between 2 and 5. It is parsed as (2 <= n) <= 5. This is evaluated by comparing 2 to n, which produces 0 (if false) or 1 (if true). This result, 0 or 1, is then used in … <= 5. Since 0 and 1 are both less than or equal to 5, the result is always 1 (for true).
To test whether n is greater than or equal to 2 and less than or equal to 5, you must write this out explicitly: 2 <= n and n <= 5, which we join with the “and” operator, &&: 2 <= n && n <= 5.
Other Issues
The proper form for including stdio.h is #include <stdio.h>, not #include stdio.h.
A proper declaration for main is int main(void), not int main().
Corrected Program
A program with these issues corrected is:
#include <stdio.h>
int main(void)
{
int n;
scanf("%d", &n); //taking input
if (n % 2 != 0)
{
printf ("Weird"); //checking first condition
}
else if (2 <= n && n <= 5)
{ //checking second condition
printf ("Not Weird");
}
else if (6 <= n && n <= 20)
{ //checking third condition
printf ("Weird");
}
else if (n > 20)
{ //checking fourth condition
printf ("Not Weird");
}
else
{
printf ("Error");
}
return 0;
}
There is a typo in the line:
if (n / 2 != 0)
The compiler will not complain, but you will get unexpected results at run time.
Here you meant to check if the remainder of division by 2 is not equal to zero (i.e.: modulus operator), and not the division by 2. This line should be
if (n % 2 != 0)
Second thing: you can't tell C to compare values in ranges like this 2 >= n >= 4. You will have to split the comparison into 2 comparisons. This line:
else if (n % 2 == 0 && 2 <= n <= 5)
Should be:
else if (n % 2 == 0 && 2 <= n && n <= 5)
You will need to fix all the lines that have this comparison as well.

My for loop seems to not be incrementing. It gets stuck on 2 (project euler 14)

I am working on project euler #14 :
Question:
The following iterative sequence is defined for the set of positive integers:
n → n/2 (n is even)
n → 3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
Problem:
When I run this code, the first for loop runs as expected. But then the variable num seems to not increment in the for loop and stays on 2 (which isn't even in the perameters of num I gave to start out with), giving the output:
2
0
1
1
repeating over and over again. Not sure why this is happening and can't find anything online.
Code:
#include <stdio.h>
int main() {
int maxcount = 0;
for (int num = 5; num < 2000000; num++) {
printf("%d\n0\n\n", num);
int count = 0;
while (num >= 1) {
count++;
if (num == 2) {
num = 1;
printf("1\n%d\n\n", count);
}
if (num > 1) {
if (num % 2 == 0) {
num = num / 2;
printf("%d\n%d\n\n", num, count);
}
else {
num = (3 * num) + 1;
printf("%d\n%d\n\n", num, count);
}
}
if (num == 1) {
break;
}
}
if (count > maxcount) {
maxcount = count;
}
}
printf("%d", maxcount);
return 0;
}
You need to introduce a new variable. You are doing:
for (int num = 5; num < 2000000; num++) {
/* collatz stuff, which modifies num, and eventually
causes it to become 1
*/
}
so when the num++ portion of the for loop runs, num becomes 2.
What you want is
for (int start = 5 ; start < 2000000 ; start++) {
int num = start;
/* collatz stuff, which modifies num */
}
since the variable start is never modified by the loop body, it will keep going up in sequence by 1, without interference.
In the while loop, you change the value of the loop variable (num).
You start with num = 5, and the inner while loop then follows Collatz's rules and gets to 1, at which point the while-loop ends.
Then the for-loop ends, and num is incremented to 2 by num++, and the next iteration of the loop begins.
In the second iteration, the while-loop immediately sees num == 2, so it sets num = 1, and the while loop ends. Then the for-loop ends, incrementing num to 2, and the cycle continues forever.
As others have said, you just need to leave the loop variable alone and use a different variable in the inner loop.

C Programming: What conditions do I put for an if statements for numbers 1 to 35 inclusive?

Okay I need help with translating sentences to condition statements in C.
For example, if I want my input to be from 1 to 35 (inclusive), and only want odd integer inputs, how would I go about making a conditional statements?
Is it:
int n;
while(1){
printf("What is the value for n you wish to use (please use an odd number?: ");
scanf("%d", &n);
if(n%2=0 && n<=35 && n>=1)
if(n<1)
break;
}
if (n%2=0 && n<=35 && n>=1)
is (almost) the condition for even numbers, those exactly divisible by 2. Note that the equality operator is ==. For odd, you want
if (n%2==1 && n<=35 && n>=1)
With this, you do not need any more if statements.
This n%2=0 should be (for odd numbers) n%2 == 1
And if you want to break on a number not matching your conditions, use something like this in the loop:
if(!((n%2 == 1) && (n<=35) && (n>=1)))
break;
}
Now if you want to break from a loops if any one of following condition get satisfies
The number must be above 1
The number must be below 35
The number must be odd
Then you can write:
if(n%2==1 || n>=35 || n<=1) break;
First, let's define the tests for 1 to 35 inclusive. C supports short circuiting, we should test the simple things -
if (n > 0 && n < 36) /* <---- 1 to 35 */
if (n >= 1 && n <= 35) /* <---- 1 to 35 */
or
#define MIN 1
#define MAX 35
if (n >= MIN && n <= MAX) /* MIN to MAX */
However, your code is incorrect. The second if will ever evaluate to true since the first requires n>=1
if(n%2=0 && n<=35 && n>=1)
if(n<1)
break;
I believe you wanted
if (n > 35 || n < 1) {
break;
}
A test for even should just continue (and not end the loop), or you could test for odd and just display those,
if (n % 2 == 0) continue;
or
if (n % 2 != 0) printf("%i\n", n);

Find out max divisor of a positive integer

I need to find the biggest divisor of a positive integer and output it. Divisor should not be 1 or be equal to the integer itself. If it's a prime number the output should be "0". I have this code so far. However it doesn't work. It only works when I use "break" instead of "return 0" statement, but according to the task I should not use break :( How can I fix it? Thnx
#include <stdio.h>
int main() {
int input, maxDiv;
int div = 2;
scanf("%d", &input);
for ( ; div <= input/2; div += 1 ) {
if ( input % div == 0 ) {
maxDiv = input / div;
return 0;
} else {
maxDiv = 0;
}
}
printf("%d\n", maxDiv);
return 0;
}
You can rewrite it this way
int main(){
int input, maxDiv = 0;
int div = 2;
scanf("%d", &input);
for(; !maxDiv; div++)
if(!(input%div))
maxDiv = input/div;
printf("%d\n", ( maxDiv == 1 || input < 0 ? 0 : maxDiv ) );
return 0;
}
It is an infinite loop that will exit as soon as maxDiv != 0. The complexity is O(sqrt (n)) as there is always a divisor of n less than or equal to sqrt(n), so the code is bound to exit (even if input is negative).
I forgot, you have to handle the case where input is zero.
Maybe you can declare a flag?
#include <stdio.h>
int main() {
int input, maxDiv;
int div = 2;
char found = 0;
scanf("%d", &input);
for ( ; div <= input/2 && !found ; div += 1 ) {
if ( input % div == 0 ) {
maxDiv = input / div;
found = 1;
} else {
maxDiv = 0;
}
}
printf("%d\n", maxDiv);
return 0;
}
You can stop the loop when you reach sqrt(input)... it's not that difficult to find a perfectly good integer sqrt function.
There's not a lot of point dividing by all the even numbers after 2. In fact there's not a lot of point dividing by anything except the primes. It's not hard to find the primes up to sqrt(INT_MAX) (46340, for 32-bit integer)... there are tables of primes freely available if you don't want to run a quick sieve to generate same.
And the loop...
maxdiv = 0 ;
i = 0 ;
sq = isqrt(input) ;
while ((maxdiv == 0) && (prime[i] < sq))
{
if ((input % prime[i]) == 0)
maxdiv = input / prime[i] ;
i += 1 ;
} ;
assuming a suitable integer sqrt function and a table of primes... as discussed.
Since you are looking for the largest divisor, is there a reason you're not looping backward to 2? If there isn't, then there should be no need for a break statement or any special logic to exit the loop as you should keep looping until div is greater than input / 2, testing every value until you find the largest divisor.
maxDiv = -1;
for (div = input / 2;
div >= 2 && maxDiv == -1;
--div)
{
if (input % div == 0)
maxDiv = div;
}
maxDiv += (maxDiv == -1);
printf ("%d\n", maxDiv);
I added the extra condition of maxDiv being -1, which is like adding a conditional break statement. If it is still -1 by the end of the loop, then it becomes 0 because maxDiv += 1 is like writing maxDiv = -1 + 1, which is 0.
Without any jump statement such as break, this sort of test is what you must do.
Also, regarding your code, if I input 40, the if statement will be triggered when div is 2, and the program will end. If the return 0 is changed to a break, maxDiv will be 2, not 20. Looping backward will find 20 since 40/2=20, and 40%20==0.
Let us denote D to the max divisor of a given composite number N > 1.
Then, obviously, the number d = N / D is the min non-trivial divisor of N.
If d would not a primer number, then d would have a non-trivial divisor p < d.
By transitivity, this implies that p is a divisor of N, but this fact would contradict the fact that d is the min divisor of N, since p < d.
So, d must be a prime number.
In particular, it is enouth to search over those numbers which are less than sqrt(N), since, if p is a prime number greater than sqrt(N) which divies N, then N / p <= sqrt(N) (if not, *p * (N / p) > sqrt(N)sqrt(N) == N, wich is absurd).
This shows that it's enough to do the search the least divisor d of N just within the range of primer numbers from 2 to sqrt(N).
For efficiency, the value sqrt(N) must be computed just once before the loop.
Moreover, it is enough a rough approximation of sqrt(N), so we can write:
#include <math.h>
#include <stdio.h>
int main(void)
{
int N;
scanf("%d",&N);
// First, we discard the case in that N is trivial
// 1 is not prime, but indivisible.
// Change this return if your want.
if (N == 1)
return 0;
// Secondly, we discard the case in that N is even.
if (N % 2 == 0)
return N / 2;
// Now, the least prime divisor of N is odd.
// So, we increment the counter by 2 in the loop, by starting in 3.
float sqrtN = fsqrt(N); // square root of N in float precision.
for(d = 3; d <= sqrtN; d += 2)
if (N % d == 0)
return N/d;
// If the loop has reached its end normally,
// it means that N is prime.
return 0;
}
I think that the problem is not well stated, since I consider that a better flag to signalize that N is prime would be a returned value of 1.
There are more efficient algorithms to determine primality, but they are beyond the scope of the present question.

Resources