seemingly ignored assignment to variables in head of for-loop - c

void main()
{
int a, b, r;
//Finf GCD by Eucledian algorithm
scanf("%d %d", &a, &b);
for( ; b == 0; (a = b), (b = r)){
r = a % b;
printf("GCD is %d", a);
}
printf("GCD is %d", a);
}
Somehow this doesn't work.
I assign a to b and b to r, but this doesn't seem to change the value of a or b.

This for(;b==0;(a=b),(b=r)) sets up the for-loop like this
do nothing to init anything
as long as b equals 0 do the loop body
between loop body executions first copy value of b to a,
then copy value of r to b
Note that the loop will never execute if b starts off non-zero.
Otherwise the loop will stop executing as soon as b becomes non-zero, from being updated with value of r.
(This is somewhat compiling an answer from comments, in order to get this out of the list of unanswered questions. Credits to dddJewelsbbb. I offer to delete this if they make an answer and ask me to.)

Find the corrected working code below, which changes the loop condition:
#include <stdio.h>
void main ()
{
int a, b, r;
//Finf GCD by Eucledian algorithm
scanf ("%d %d", &a, &b);
for (; r > 0; a = b, b = r)
{
r = a % b;
}
printf ("GCD is %d", a);
}
Test by giving inputs: 16, 12
16
12
GCD is 4
Code explanation:
The code is the direct implementation of Euclid's algorithm to find GCD. Here the divisor (one of the number) is used to obtain a remainder (after dividing the second number as dividend). Next, the remainder becomes the divisor and the earlier divisor becomes the dividend and this process continues till remainder is zero.
There is plenty of scope in the code to make it more elegant and handle corner cases. I corrected the exact same code as minimum as possible to spot the exact error (which was in the for loop condition).

Related

Example of a colloquium exam

Check the image
This is my 1st post so have that in mind while reading my question.
I have an exam of a colloquium but my code does not provide me the correct result.
So if anyone could help me that would be great. :)
These are the informations that are provided in the exam:
A function y=f(x)=ax^2+bx+c
We have to find the surface that is below the chart but keep in mind that dx(Delta X)=B-A and the height goes like this: A,A+dx,A+2dx, .... , B-dx.
As dx value gets lower the surface will be more accurate.
You have to write the program so that the surface with precision 0.001
This is my code so could someone who is good in C check it please.
Thank you.
#include <stdio.h>
#include <math.h>
int main()
{
int a,b,c;
double A,B,dx,p,D,q,x,y,nv,nv1,nv2,sv;
do{
printf("Insert a & b: "),scanf("%lf %lf",&A,&B);
} while(A<1 || B<1);
nv=dx=B-A;
do{
printf("enter odds: "),scanf("%d %d %d",&a,&b,&c);
p=(-b)/2;
D=sqrt(pow(b,2)-4*a*c);
q= -D/4*a;
} while( a<0 || p<0 || q<0);
do{
sv=nv;
dx/=2;
nv=0;
for(x=A;x<p;x+=dx)
for(dx=B-A;dx<q;dx/=2)
nv1+=x*dx;
for(y=p;y<=B;y+=dx)
for(dx=q;dx<B;dx/=2)
nv2+=y*dx;
nv=nv1+nv2;
}while(fabs(nv-sv)>0.001);
printf("The surface is %lf",nv);
return 0;
}
You want to find the approximation of a definite integral of a quadratic function. There are several issues with your code:
What is the restriction of A ≥ 1 and B ≥ 1 for? A parabola is defined over the whole abscissa. If anything, you should enforce that the input is numeric and that two values were given.
You don't need to find the vertex of the parabola. Your task is to create small rectangles based on the left x value of each interval as the image shows. Therefore, you don't need p and q. And you shouldn't enforce that the vertex is in the first quadrant on the input without indication.
Why are the coefficients of the parabola integers? Make them doubles to be consistent.
Because you don't need to know the vertex, you don't need to split your loop in two. In your code, you don't even check that p is between A and B, which is a requirement of cour code.
What is the inner loop for? You are supposed to just calculate the area of the current rectangle here. What's worse: you re-use the variable dx as iteration variable, which means you lose it as an indicator of how large your current interval is.
The repeated incrementing of dx may lead to an accumulated floating-point error when the number of intervals is large. A common technique to avoid this is to use an integer variable for loop control and the determine the actual floating-point variable by multiplication.
The absolute value as a convergence criterion may lead to problems with small and big numbers. The iteration ends too early for small values and it may never reach the criterion for big numbers, where a difference of 0.001 cannot be resolved.
Here's a version of your code that puts all that into practice:
#include <stdio.h>
#include <math.h>
int main()
{
double a, b, c;
double A, B;
printf("Lower and upper limit A, B: ");
scanf("%lf %lf", &A, &B);
printf("enter coefficients a, b, c: ");
scanf("%lf %lf %lf", &a, &b, &c);
double nv = 0;
double sv;
int n = 1;
do {
int i;
double dx;
sv = nv;
n *= 2;
dx = (B - A) / n;
nv = 0;
for (i = 0; i < n; i++) {
double x = A + i * (B - A) / n;
double y = a*x*x + b*x + c;
nv += dx * y;
}
} while(fabs(nv - sv) > 0.0005 * fabs(nv + sv));
printf("Surface: %lf\n", nv);
return 0;
}
The code is well-behaved for empty intervals (where A = B) or reversed intervals (where A > B). The inpt is still quick and dirty. It should really heck that the entered values are valid numbers. There's no need to restrict the input arbitrarily, though.

Recursion that branches running out of memory

I have a programming assignment that goes like this:
You are given three numbers a, b, and c. (1 ≤ а, b, c ≤ 10^18)
Each time you have two choises, either add b to a (a+=b), or add a to b (b+=a). Write a program that will print out YES or NO depending on whether you can get to c by adding a and b to each other.
I've tried solving this problem using recursion that branches to two branches every time where one branch stores a+b, b and the other branch stores a, b+a. In every recursive call, the function checks the values of a and b, and if they are equal to c the search stops and the function prints YES. The recursion stops when either a or b have a value greater than c.
Here's how the branching works:
And here's the code in C:
#include <stdio.h>
#include <stdlib.h>
void tree(long long int a, long long int b, long long int c){
if(a==c || b==c){
printf("YES");
exit(0);
}
else if(a<c && b<c){
tree(a, b+a, c);
tree(a+b, b, c);
}
}
int main(){
long long int a, b, c;
scanf("%I64d", &a);
scanf("%I64d", &b);
scanf("%I64d", &c);
tree(a, b, c);
printf("NO");
return 0;
}
Now, this program works for small numbers, but since a b and c can be any 64-bit number, the tree can branch itself a few billion times, and the program runs out of memory and crashes.
My question is: Is there any way i can improve my code, or use any other way (other then recursion) to solve this?
OK I'll have to admit that this turned out to be a fascinating question. I really thought that there should be a quick way of finding out the answer but the more I looked at the problem, the more complex it became. For example, if you zigzag down the tree, alternating a+=b with b+=a, you are essentially creating the fibonacci sequence (imagine a=2 and b=3 to start with). Which means that if you could find the answer quickly, you could somehow use a similar program to answer "is c a fibonacci number"?
So I never came up with anything better than searching the binary tree. But I did come up with a way to search the binary tree without running out of memory. The key trick in my algorithm is that at every node you need to search two child nodes. But you don't need to recurse down both paths. You only need to recurse down one path, and if that fails, you can iterate to the other child. When recursing, you should always pick the path where the smaller number changes. This guarantees that you are doubling the minimum element on each recursion level, which guarantees that you will only recurse 64 times max before your minimum element will exceed 2^64.
So I wrote the program and ran it, and it worked just fine. That is until I entered a very large number for c. At that point, it didn't finish. I found from testing that the algorithm appears to have an O(N^2) running time, where N = c. Here are some sample running times (all on a desktop running 64-bit Windows).
Inputs Time in minutes
------ ---------------
a=2 b=3 c=10000000000 (10^10): 0:20
a=2 b=3 c=100000000000 (10^11): 13:42
a=2 b=3 c=100000000001 : 2:21 (randomly found the answer quickly)
a=2 b=3 c=100000000002 : 16:36
a=150 b=207 c=10000000 (10^7) : 0:08 (no solution)
a=150 b=207 c=20000000 : 0:31 (no solution)
a=150 b=207 c=40000000 : 2:05 (no solution)
a=150 b=207 c=100000000 (10^8) : 12:48 (no solution)
Here is my code:
// Given three numbers: a, b, c.
//
// At each step, either do: a += b, or b += a.
// Can you make either a or b equal to c?
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
static int solve(uint64_t a, uint64_t b, uint64_t c);
int main(int argc, char *argv[])
{
uint64_t a = 0, b = 0, c = 0;
if (argc < 4) {
printf("Usage: %s a b c\n", argv[0]);
exit(0);
}
a = strtoull(argv[1], NULL, 0);
b = strtoull(argv[2], NULL, 0);
c = strtoull(argv[3], NULL, 0);
// Note, by checking to see if a or b are solutions here, solve() can
// be made simpler by only checking a + b == c. That speeds up solve().
if (a == c || b == c || solve(a, b, c))
printf("There is a solution\n");
else
printf("There is NO solution\n");
return 0;
}
int solve(uint64_t a, uint64_t b, uint64_t c)
{
do {
uint64_t sum = a + b;
// Check for past solution.
if (sum > c)
return 0;
// Check for solution.
if (sum == c)
return 1;
// The algorithm is to search both branches (a += b and b += a).
// But first we search the branch where add the higher number to the
// lower number, because that branch will be guaranteed to double the
// lower number, meaning we will not recurse more than 64 times. Then
// if that doesn't work out, we iterate to the other branch.
if (a < b) {
// Try a += b recursively.
if (solve(sum, b, c))
return 1;
// Failing that, try b += a.
b = sum;
} else {
// Try b += a recursively.
if (solve(a, sum, c))
return 1;
// Failing that, try a += b.
a = sum;
}
} while(1);
}
Edit: I optimized the above program by removing recursion, reordering the arguments so that a is always less than b at every step, and some more tricks. It runs about 50% faster than before. You can find the optimized program here.
Based on comment from #Oliver Charlesworth, this is an iterative not recursive solution so it won't solve the homework. But it's pretty simple, I step through b because it is larger than a (although that is not entirely clear from the OP) hence fewer iterations required.
#include <stdio.h>
int main(){
unsigned long long int a, b, c, bb;
scanf("%I64u", &a);
scanf("%I64u", &b);
scanf("%I64u", &c);
if (a >= 1 && a < b && b < c) {
for (bb=b; bb<c; bb+=b) {
if ((c - bb) % a == 0) {
printf ("YES\n");
return 0;
}
}
}
printf("NO\n");
return 0;
}

The difference between n++ and ++n at the end of a while loop? (ANSI C)

this is probably a dumb question but I just can't figure it out. It has to do with the differences between n++ and ++n (which I thought I understood but apparently not).
#include <stdio.h>
#include <math.h>
long algorithmA(int n);
long algorithmB(int n);
int main(){
long A, B;
A = B = 0;
int n = 1;
while(A >= B){
A = algorithmA(n);
B = algorithmB(n);
n++;
}
printf("At n = %d, Algorithm A performs in %ld seconds & "
"Algorithm B performs in %ld seconds.", n, A, B);
}
long algorithmA(int n){
return pow(n,4) * 86400 * 4;
}
long algorithmB(int n){
return pow(3,n);
}
Here you can probably tell I'm trying to see at what point Algorithm A outperforms Algorithm B. The functions and units of time were given to me in a homework problem.
Anyways, I always thought that the order of "++" would not matter at the end of a while loop. But if I put ++n instead of n++, I get the wrong answer. Can somebody explain why?
Edit: Well it WAS showing 24 with ++n and 25 with n++, but it must have been for another reason. Because I just checked now and there is no difference. Thanks for your patience and time guys, I just wish I knew what I did!
If you increment without assignment, no difference. However, in the following circumstances, there is:
int n = 1;
int x = n++; // x will be 1 and n will be 2
In this example, the statement gets executed prior to the increment.
int n = 1;
int x = ++n; // both x and n will be 2
However, in this example, increment occurs prior to the execution of the statement.
Operator precedence can help you out.
The only difference between n++ and ++n is that n++ yields the original value of n, and ++n yields the value of n after it's been incremented. Both have the side effect of modifying the value of n by incrementing it.
If the result is discarded, as it is in your code, there is no effective difference.
If your program is behaving differently depending on whether you write
n++;
or
++n;
it must be for some other reason.
In fact, when I compile and execute your program on my system, I get exactly the same output in both cases. Adding newlines to the output format, I get:
At n = 25, Algorithm A performs in 114661785600 seconds &
Algorithm B performs in 282429536481 seconds.
You haven't told us what output you're getting. Please update your question to show the output in both cases.
The prefix versions (++n) alter the variable and then pass along its value.
The postfix version (n++) pass along the current value and then alter the variable.

Explain the working of a program that prints the GCD and LCD of two numbers

I know its very simple but I can't find out what the variable t is for.
int main() {
int a, b, x, y, t, gcd, lcm;
printf("Enter two integers\n");
scanf("%d%d", &x, &y);
a = x;
b = y;
while (b != 0) {
t = b;
b = a % b;
a = t;
}
gcd = a;
lcm = (x*y)/gcd;
printf("Greatest common divisor of %d and %d = %d\n", x, y, gcd);
printf("Least common multiple of %d and %d = %d\n", x, y, lcm);
return 0;
}
If I remove the usage of variable t, the input has to be given in decreasing order (i.e. highest input first). If t is used everything works fine. I am very new to programming so please help.
This is Euclid's Algorithm for calculating the GCD.
function gcd(a, b){
while (b ≠ 0){
t := b;
b := a mod t;
a := t;
}
return a
}
This logic reduces the value of a and b. t is a dummy variable holding the value of b, while the next new value of b is being calculated. Which will be even less in magnitude. So eventually we will be able to terminate the algorithm with the required result.
In this t is for temporary holding.
In this while loop a%b has to be set to b, and b's value has to be set to a.
To avoid loss of b's value.
Say you have 2 values - old 'a' and old 'b' (no 't').
The 'while' loop is supposed to update those values to new 'a' and new 'b'.
Every recalculation of new 'a' requires old 'b', and every recalculation of new 'b' requires old 'a'.
However, if you calculate 'b' first, it overwrites the old value and you can't calculate 'a' correctly. Same goes the other way around - recalculate new 'a', you lose the old value and can't use it to calculate 'b'. Therefore you need a temporary variable in which to store the old value of whichever variable ('a' or 'b') you recalculate first in an iteration, then use this cached value for calculating the other :) 't' is this temporary variable.
The use of a temporary variable is a common programming idiom. It is used to hold a copy of a variable's value so that the value can be used later after the variable is updated with a different value. Perhaps the simplest use case is the swap, also known as exchange.
/* swap the values held by a and b */
t = b; /* t holds the value in b */
b = a; /* b gets the value in a */
a = t; /* a gets the value in t */
The logic of the while loop is not fundamentally different from the illustration above.
The algorithm that is implemented is Euclid's algorithm. It is based on the division theorem, which states that for positive a and b, there exists q such that a = q*b + r and 0 <= r < b. In C, r can be computed with a % b.
In the case that a is smaller than b, then a % b is a. So, the algorithm allows a and b to switch positions at the next iteration.
If you want a formulation of the algorithm without a temporary, you can use a circular buffer instead.
int r[3] = { a, b, a % b };
int i = 0;
while (r[(i + 2) % 3]) {
++i;
r[(i + 2) % 3] = r[i % 3] % r[(i + 1) % 3];
}
gcd = r[(i + 1) % 3];
According to your program's logic,
Consider two numbers - 2 and 3.
To calculate the GCD,
Calculate 2 % 3. The result is 2 (which is not 0) so continue.
Calculate 3 % result => 3 % 2. The result is 1 (which is not 0) so continue.
Calculate 2 % result => 2 % 1. This answer is 0. Thus our GCD is the second number (i.e) 1.
So basically, your t helps you store the second number in each iteration so that in the next iteration, your first number (i.e. the number to the left of the '%' operator) was the previous iteration's second number. (I hope that didn't confuse the crap out of you)
All this is necessary because you're overwriting the second number in each iteration with the result of the '%' operation.

fibonacci series gone wrong?

we have been asked to write a program to generate fibonacci series as our homework.
so i wrote a program that generates the first n fibonacci numbers .here is my frist code that dosent work properly
# include <stdio.h>
void main()
{
int a = -1, b = 1, c = 0, i, n, sum = 0 ;
printf("Enter the limit : ") ;
scanf("%d", &n) ;
printf("\nThefibonacci series is : \n\n") ;
for(i = 1 ; i <= n ; i++)
{
c = a + b ;
printf("%d \t", c) ;
b=c;
a=b;
}
}
so i tried various combinations and i found out that my code would work well if i interchanged the 12th and 13th lines. i.e
# include <stdio.h>
void main()
{
int a = -1, b = 1, c = 0, i, n, sum = 0 ;
printf("Enter the limit : ") ;
scanf("%d", &n) ;
printf("\nThefibonacci series is : \n\n") ;
for(i = 1 ; i <= n ; i++)
{
c = a + b ;
printf("%d \t", c) ;
a=b;
b=c;
}
}
It is the same logic right.
why does the first code give me wrong output?
what are segmentation faults?(my compiler frequently tells me that there are segmentation faults in my code)
P.S-i am a begginer.Just three weeks into c language and we are learning about loops.
The ordering of statements matters.
b = c;
a = b;
When this runs, b and a will both be equal to the original value of c, and the old value of b has been lost. This is probably not what you wanted.
a = b;
b = c;
When this runs, a will equal the old value of b, and b will equal the original value of c.
In Fibonacci series, a new number is generated as sum of previous two numbers.
Lets say previous two numbers were A and B and the newly generated number is C. Now for the next iteration you need to forget A and B & C are your new previous numbers.
To make B and C you new A and B you need to do:
A = B // B becomes the new A
B = C // C becomes the new B
what you are doing is:
B = C // C becomes the new B, but you've not saved the old value of B!!!
A = B // Old value of B gone..B is now C, which is assigned to A
Lines are executed in order, so in the first example b becomes c before a becomes b, in effect you are assigning c to both a and b creating some kind of exponential series (but of zeroes) instead of the fibonacci sequence.
A segmentation fault means that your program is accessing memory somewhere where it is not allowed to access memory, usually because you are dereferencing an invalid pointer or accessing an array out of bounds.
Look at this in isolation:
c = a + b ;
printf("%d \t", c) ;
b=c;
a=b;
The value of both a and bafter performing this will be c.
c = a + b ;
printf("%d \t", c) ;
a=b;
b=c;
If you re-arrange the statements, a gets the old value of b, and b gets the new value of c.
It is the same logic right. why does the first code give me wrong output?
Have you ever wondered, why
printf("Enter the limit : ") ;
scanf("%d", &n) ;
printf("\nThe fibonacci series is : \n\n") ;
first outputs Enter the limit, then waits for you to input a number, then outputs The fibonacci series is – in that particular order?
Why not the other way around or everything at the same time?
What are segmentation faults?
A simple google search would have given you tons of explanations. It means you have accessed memory, that is not yours to access.

Resources