Help with While Loop please! Thanks!

Discussion in 'Mac Programming' started by cybrscot, Feb 10, 2011.

  1. cybrscot, Feb 10, 2011
    Last edited: Feb 10, 2011

    cybrscot macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #1
    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
    
     
  2. lee1210, Feb 10, 2011
    Last edited: Feb 10, 2011

    lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    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.
     
  3. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #3
     
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    You are dividing. The algorithm only requires the remainder, which mod gives you.

    -Lee
     
  5. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #5
    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
    
    
     
  6. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #6
    Sorry but I think I need a bit more direction here, not sure how to implement what you suggested.
     
  7. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #7
    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
     
  8. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #8
    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.
     
  9. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #9
    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 ;
    	
    }	
     
  10. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #10
    Change that to

    Code:
    		printf("start: %d %d",m,n);
                    m = n ;
    		printf("middle: %d %d",m,n);
    		n = m % n ;
    		printf("end: %d %d",m,n);
    
    
    to see why it isn't working the way you expect it to.

    B
     
  11. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #11

    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.
     

Share This Page