Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Last night I successfully produced my first Cocoa application, a simple calculator. Simple or not, I was thrilled that it worked and I actually used it on my Mac! How exciting, made me want to keep charging forward! I guess it's Cocoa's equivalent to C's "hello, world" program. Anyway, today brings a new C challenge. Here is the problem, directly from my book.

"Write a program that asks the user to enter two integers, then calculates and displays their greatest common divisor (GCD)

Should look like this to the user.....

Enter two integers: 12 28
Greatest common divisor: 4

Hint: The classic algorithm for computing the GCD, known as Euclid's algorithm, goes as follows. Let m and n be variables containing the two numbers. Divide m by n. Save the divisor in m, and save the remainder in n. If n is 0, then stop. m contains the GCD. Otherwise repeat the process, starting with the division of m by n. "

So I worked the math out on paper for a few combinations of numbers to become re-acquainted with GCD and how this Euclid's algorithm will work. Seems easy enough.

I will
1. Declare int m, n ;
2. Ask the user to input two numbers
3. scanf and accept the two numbers into &m, &n
4. Then begin my while loop, because as long as (m % n != 0), I want the loop to continue.
5. The problem says to divide m by n. Then save the divisor in m. I don't know the point in doing the division. Since n is the divisor, I can just say m = n. Saving n into m.
6. Then it wants me to save the remainder into n. So I figure I will do something like (n = (m % n))

All of this of course is happening as long as (m % n != 0) (if the remainder is not 0, I want the loop to run. While the loop is running, is will assign n to m, then assign the REM to n, then check to see if (m % n != 0) again, and so on. That's a loop that will continue until the REM does result in 0.

Of course if the controlling expression (m % n != 0) is false and the REM is 0, then I expect it to break from the loop and printf (The GCD is %d, n)

Partial Pseudo code (not complete, but thought process)

int firstnum, secondnum ;

printf (blah blah blah)
scanf (%d,%d, &firstnum, &secondnum)

while (firstnum % secondnum != 0)
firstnum = secondnum and && secondnum = firstnum % secondnum


Now, I'm getting an error that I think is a problem with my loop. I will post two different codes that I wrote. They each have some things commented out in the while loop. They indicate several different ways I tried to write my loop to get it to work.

The reason I think the problem is with my loop is because in both code examples, I do get correct program performance and output if the user enters two integers that REM out to 0 the first time. (example if user input 10 and 5, the REM is 0, and the programs works) But anything else I'm getting a "floating point exception", whatever that is. Check it out below, thanks in advance.

I hope the code below shows that I'm starting to understand things a little bit and my thought process is hopefully correct. (even though the code is obviously wrong) I think it's of some merit that I thought of two different ways to solve the same problem. Maybe they can both work, maybe neither, but I'm encouraged that they both produce acceptable output under at least specific circumstances. It originally took me about 30 min to lay out the flow on paper, then write the code. But I've spent the past 4 hours tweeking it (commented lines) to see if I could get it to work.

Code:
#include <stdio.h>

main ()
{ 

	int m = 0, n = 0 ;
	
	printf ("Enter two numbers (separated by a space): ") ;
	scanf ("%d%d", &m,&n) ;
	
	while (m % n != 0) {
	//(m = n) && (n = m % n) ;             this line by itself
	//m / n ;              these three
	//m = n ;               lines 
	//n = m % n ;           together
	if (m % n != 0)                //these three
		m = n ;                    //lines
		n = m % n ;               // together
	}
	
		
		
		
		
		
		
		
	printf ("Greatest Common Divisor: %d\n", n) ;
	
	return 0 ;
	
}


Terminal Output:

Code:
Scott-Deans-MacBook-Pro:~ scottdean$ gcc ~/documents/Ch_6_loop.c
Scott-Deans-MacBook-Pro:~ scottdean$ ./a.out
Enter two numbers (separated by a space): 100 50
Greatest Common Divisor: 50
Scott-Deans-MacBook-Pro:~ scottdean$ ./a.out
Enter two numbers (separated by a space): 34 28
Floating point exception


Next Code Example:

Code:
#include <stdio.h>

main ()
{

	int m, n ;
	
	printf ("Enter two numbers (separated by a space): ") ;
	scanf ("%d%d", &m,&n) ;
	
	if (m % n == 0 )
		printf ("The GCD is: %d\n", n) ;
		
	else
		while (m % n != 0) {
		//(m = n) && (n = m % n) ;
		m = n ;
		n = m % n ;
		
		}
		
		
	//printf ("The GCD is: %d\n", n) ;
	
	return 0 ;
	
}


Terminal Output:

Code:
Scott-Deans-MacBook-Pro:~ scottdean$ ./a.out
Enter two numbers (separated by a space): 100 50
The GCD is: 50
Scott-Deans-MacBook-Pro:~ scottdean$ ./a.out
Enter two numbers (separated by a space): 50 100
Floating point exception
 
Last edited:

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Your logic seems to be on track, but actually executing it is getting the better of you. The issue seems to be that you can't perform some steps simultaneously. You need to get the remainder before changing either values, then you need to move n to m, then save the remainder in n. So it might be something like:
int modResult = m % n;
m = n;
n = modResult;

When the loop exits it means that if you did the division again the remainder would be 0. That means that the GCD is in n, as you didn't technically "finish" the algorithm as described by performing that "last" division to get n equal to 0, and m equal to the GCD.

-Lee

EDIT: The floating point exception is a divide by 0 issue. You can't have the right operand of a % be 0 just like the right operand of / can't be 0. You'll have to account for this in whatever code you come up with, maybe including n != 0 in your while condition, etc.
 
Last edited:

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Your logic seems to be on track, but actually executing it is getting the better of you. The issue seems to be that you can't perform some steps simultaneously. You need to get the remainder before changing either values, then you need to move n to m, then save the remainder in n. So it might be something like:
int modResult = m % n;
m = n;
n = modResult;

When the loop exits it means that if you did the division again the remainder would be 0. That means that the GCD is in n, as you didn't technically "finish" the algorithm as described by performing that "last" division to get n equal to 0, and m equal to the GCD.

-Lee

Thanks Lee, I'll give it another go tomorrow. I feel pretty close. Why did my book say, "Hint: The classic algorithm for computing the GCD, known as Euclid's algorithm, goes as follows. Let m and n be variables containing the two numbers. Divide m by n. Why divide m by n? I see you didn't suggest to do that, and I didn't think it would be of importance either. Was he just explaining how Euclid's algorithm works? So we can set up the problem in our heads or on paper? Rather than actually implying that we should include that division in the program?
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Thanks Lee, I'll give it another go tomorrow. I feel pretty close. Why did my book say, "Hint: The classic algorithm for computing the GCD, known as Euclid's algorithm, goes as follows. Let m and n be variables containing the two numbers. Divide m by n. Why divide m by n? I see you didn't suggest to do that, and I didn't think it would be of importance either. Was he just explaining how Euclid's algorithm works? So we can set up the problem in our heads or on paper? Rather than actually implying that we should include that division in the program?

You are dividing. The algorithm only requires the remainder, which mod gives you.

-Lee
 

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Your logic seems to be on track, but actually executing it is getting the better of you. The issue seems to be that you can't perform some steps simultaneously. You need to get the remainder before changing either values, then you need to move n to m, then save the remainder in n. So it might be something like:
int modResult = m % n;
m = n;
n = modResult;

I still don't get it. Are you saying above to add modResult = m % n: to my int declarations? So I have int m, n, modResult = m % n; ???:confused::confused:

I did that, then inserted the modResult = m % n; into my loop, then the m = n assignment, then the n = modResult assignment.

Now the whole thing doesn't work at all.


Code:
#include <stdio.h>

main ()
{ 

	int m, n, modResult = m % n;
	
	
	printf ("Enter two numbers (separated by a space): ") ;
	scanf ("%d%d", &m,&n) ;
	
	while (m % n != 0) {
	modResult = m % n;
	m = n;
	n = modResult;
	
	//(m = n) && (n = (m % n)) ;             //this line by itself
	//m / n ;              these three
	//m = n ;               //lines 
	//n = m % n ;           //together
	//if (m % n != 0)                //these three
	//	m = n ;                    //lines
	//	n = (m % n) ;               // together
	}
	
		
		
		
		
		
		
		
	printf ("Greatest Common Divisor: %d\n", n) ;
	
	return 0 ;
	
}


Terminal:

Code:
Scott-Deans-MacBook-Pro:~ scottdean$ gcc ~/documents/Ch_6_loop.c
Scott-Deans-MacBook-Pro:~ scottdean$ ./a.out
 

balamw

Moderator emeritus
Aug 16, 2005
19,366
979
New England
Code:
	int m, n, modResult [COLOR="Red"]= m % n[/COLOR];

Just get rid of the red highlighted bit, it works fine. You can't calculare m%n there because m and n have no values yet. Lee confused you by declaring it in place. In C you can declare a variable anywhere you need it not just in the declaration block.

A cleaner (IMHO) loop would be:
Code:
modResult = m % n; //get first value of modResult for input values	
while (modResult != 0) {	
  m = n; //get new values of m and n per the algorithm
  n = modResult;
  modResult = m % n; //get the new value of modResult from new m and n
}

B
 

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Just get rid of the red highlighted bit, it works fine. You can't calculare m%n there because m and n have no values yet. Lee confused you by declaring it in place. In C you can declare a variable anywhere you need it not just in the declaration block.

A cleaner (IMHO) loop would be:
Code:
modResult = m % n; //get first value of modResult for input values	
while (modResult != 0) {	
  m = n; //get new values of m and n per the algorithm
  n = modResult;
  modResult = m % n; //get the new value of modResult from new m and n
}

B

Ahh, thanks again! Now it's working. I guess again I was pretty close, just can't close the deal! :D My biggest problem I think is knowing where to put my code. I see what you and Lee did, and it makes sense, but of all the things I tried, that wasn't one of them. I need to figure out where everything goes, I never thought of creating another int variable and determining the REM before the loop.

I also pasted below my "other" code that I did for the same problem. I haven't made any changes (ie, the ones you just helped me with), but before I do, do you think I could make this code also work for the same problem? I want to know because it will help me in understanding that what I'm thinking and the way I' m going about solving these problems is correct. I've learned enough here to know there is more than one way to skin a cat, just want to know if my other program (incomplete)is one of them.

Thanks! I will study carefully!

Edit: Forgot to paste code here, it's in the next post.
 

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Here is my other code....

Code:
#include <stdio.h>

main ()
{

	int m, n ;
	
	printf ("Enter two numbers (separated by a space): ") ;
	scanf ("%d%d", &m,&n) ;
	
	if (m % n == 0 )
		printf ("The GCD is: %d\n", n) ;
		
	else
		while (m % n != 0) {
		//(m = n) && (n = m % n) ;
		m = n ;
		n = m % n ;
		
		}
		
		
	//printf ("The GCD is: %d\n", n) ;
	
	return 0 ;
	
}
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Here is my other code....

Code:
#include <stdio.h>

main ()
{

	int m, n ;
	
	printf ("Enter two numbers (separated by a space): ") ;
	scanf ("%d%d", &m,&n) ;
	
	if (m % n == 0 )
		printf ("The GCD is: %d\n", n) ;
		
	else
		while (m % n != 0) {
		//(m = n) && (n = m % n) ;
		m = n ;
		n = m % n ;
		
		}
		
		
	//printf ("The GCD is: %d\n", n) ;
	
	return 0 ;
	
}


This is what I meant when i said you were hoping you could do things "simultaneously" and you can't do that in practice. That's why i suggested introducing an intermediate variable. If you step through your while loop with some test values:
m = 35
n = 49
while(m (value 35) % n (value 49) != 0) { //True, so loop
m = n (value 49); //Result, m = 49, n=49
n = m (value 49) % n (value 49); //Result, n = 0, m = 49
while(m (value 49) % n (value 0) != 0) { //Crash, divide by 0
--game over

So you can see, assigning the value of n to m before the mod will always result in n being assigned the value of 0, resulting in a crash when you try to divide by 0 to get the remainder of the division with %. This will be true for any inputs.

So... you need to check before you do ANYTHING whether or not m or n is zero. If either is 0, bad times, bail. From there... I guess I feel like you must use an intermediate variable for temporary storage, but there might be some cleverness to avoid it. I don't really think cleverness is the right path, though, especially if it sacrifices clarity.

-Lee

EDIT: balmw got in right before I did with a suggestion on seeing this yourself. I think it would be good practice to just run the code "on paper" as well as having prints to show you what's going on.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.