Thread: A little homework help?

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    3

    A little homework help?

    Hello. I ran into an issue (which I fixed) during the creation of a lab program and was wondering if you all could clarify why it happened. I'd also appreciate it if you could make suggestions as to alternative ways of completing the assignment, since I am not sure if I am making this more convoluted than it needs to be.

    The assignment is to create a program that calculates change. The user provides the amount due and the amount received, and the program calculates how many dollars, quarters, dimes, etc, the customer should receive.

    Here is what I wrote:

    Code:
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    void main() {
    	int dollars = 0;
    	int quarters = 0;
    	int dimes = 0;
    	int nickels = 0;
    	int pennies = 0;
    	double due;
    	double received;
    
    	cout << "Please enter the amount due:\n";
    
    	cin >> due;
    
    	cout << "Please enter the amount received:\n";
    
    	cin >> received;
    
    	due = received - due;
    	
    
    	if ( due >= 1 ) {
    		dollars = static_cast<int>( due );
    		due -= dollars;
    	}
    	
    	if ( due >= .25 ) {
    		quarters = static_cast<int>( due / .25 );
    		due -= quarters * .25;
    	}
    
    	if ( due >= .10 ) {
    		dimes = static_cast<int>( due / .10 );
    		due -= dimes * .10;
    	}
    
    	if ( due >= .05 ) {
    		nickels = static_cast<int>( due / .05 );
    		due -= nickels * .05;
    	}
    
    	if ( due > 0 ) {
    		pennies = static_cast<int>( due / .01 );
    	}
    
    	cout << "Supply the customer with:\n"
    		 << dollars << " dollar(s)\n"
    		 << quarters << " quarter(s)\n"
    		 << dimes << " dime(s)\n"
    		 << nickels << " nickel(s)\n"
    		 << pennies << " pennies";
    
    	cin.get();
    	cin.get();
    	
    }
    I know it's probably a mess to you guys.

    Anyway, if you change the dollars, quarters, etc, variables to doubles, the program works flawlessly. However, if you retain them as ints and attempt to use a difference of say, .72 between the two values, it indicates that you should use only one penny instead of two. The same is true for a difference of .73, where it suggests 2 pennies instead of 3.

    Why does this happen?

    Besides the aforementioned curiosity, I would also like to know if there is any way to get rid of all of the if statements, and just in general how I could optimize things.

    Thanks guys.
    Last edited by nwkegan; 02-23-2010 at 07:51 PM.

  2. #2
    Registered User NeonBlack's Avatar
    Join Date
    Nov 2007
    Posts
    431
    What's probably happening is that somewhere along the line, for example, what should be 3 is being stored in the double as 2.9999999 something. This gets cout'ed as 3, but when you truncate to int, it becomes 2.

    (I hope that makes sense. I'm running on low sleep right now)

    I would suggest doing all of your calculations using number of cents as integer variables instead of doubles.
    Using doubles, you are just going to run into rounding issues.
    I copied it from the last program in which I passed a parameter, which would have been pre-1989 I guess. - esbo

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Ditto. Money is not a floating point value -- it has fixed precision:
    Code:
    int cents = 533;
    printf("$%d.%02d\n", cents/100, cents%100);
    You can use modulus to get the change (nickels, quarters) too.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    Registered User
    Join Date
    Feb 2010
    Posts
    3
    How can I do that, though? Would I need to use a string and then convert it to an int without the decimal?

    Thanks, btw! I appreciate the help. : )

  5. #5
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    How can I do that, though? Would I need to use a string and then convert it to an int without the decimal?
    That would be the politically correct way.

    Or you can "cheat" and do something like
    Code:
    double dollars = 1.499999999999;
    int decicents = dollars * 1000; // 1499
    int cents = (decicents+5) / 10; // (1504) / 10 = 150
    Using the +5 rounding trick (+5 then truncate = round).

  6. #6
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Actually, this should work, too.

    Code:
    double dollars = 1.499999999999;
    int cents = (dollars + 0.005) * 100;

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cyberfish View Post
    That would be the politically correct way.

    Or you can "cheat" and do something like
    WHY??? This just gets zanier...eventually you are going to end up with a "more or less" accurate balance sheet.

    Quote Originally Posted by nwkegan View Post
    How can I do that, though? Would I need to use a string and then convert it to an int without the decimal?
    Not quite. Just read it into a float and multiply by 100.
    Code:
    	float x;
    	int cents;
    
    	cin >> x;
    	cents = x*100;
    This is okay because no precision is lost.

    The problem with floating point numbers is dividing a single unit by a non-power of two value. So 1/2, 1/4, 1/8 etc, are okay. 1/3 or 1/5 or 1/10 will affect the precision. This is pretty significant since 1/10 is 0.1 -- you would think 0.1 is safe. But run this and look at the output:
    Code:
    #include <iostream>
    using namespace std;
    
    int main() {
            float i;
    	cout.precision(10);
            for (i=0.0f; i<20; i+=0.1f) 
                    cout << i <<endl;
            
            return 0;
    }
    The reason this is screwed up is because 0.1 cannot be precisely represented in a computer using floating point numbers. The output differs between 32-bit and 64-bit systems as well.
    Last edited by MK27; 02-24-2010 at 06:38 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User
    Join Date
    Feb 2010
    Posts
    1
    Sorry for the new account, having some issues.

    I am still having problems with precision even after trying your methods.

    Here is what I've got:

    Code:
    #include <iostream>
    #include <cmath>
    #include <string>
    
    using namespace std;
    
    void main() {
    	double due;
    	double received;
    	int cents;
    
    	cout<< "Please enter the amount received:\n";
    
    	cin>> received;
    
    	cout<< "Please enter the amount due\n";
    
    	cin>> due;
    
    	cents = ( received - due ) * 100;
    
    	cout<< "\n" << cents << "\n" << ( received - due ) << "\n";
    	cout<< "Provide the customer with:\n";
    	cout<< cents/100 << " dollars\n";
    
    	cents = cents % 100;
    
    	cout<< cents/25 << " quarters\n";
    
    	cents = cents % 25;
    
    	cout<< cents/10 << " dimes\n";
    
    	cents = cents % 10;
    
    	cout<< cents/5 << " nickels\n";
    
    	cents = cents % 5;
    
    	cout<< cents << " pennies\n";
    
    	cin.get();
    	cin.get();
    }
    What am I doing wrong? Is this what you meant about modulus? Also, just as a passing interest, are there any glaring problems with my code convention? I'm always afraid I'm making things unreadable.

    P.S. The +.005 trick worked, I would just like to clean things up as much as possible.
    Last edited by kegano; 02-24-2010 at 05:15 PM.

  9. #9
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Quote Originally Posted by MK27 View Post
    Code:
    	float x;
    	int cents;
    
    	cin >> x;
    	cents = x*100;
    This is okay because no precision is lost.
    It's possible that x is slightly below the "real" value, and you will be off by 1 cent.

    Eg. if x = 1.499999, x*100 = 149.99999 and cents = 149. The +0.005 trick is required to round it properly.

  10. #10
    Registered User NeonBlack's Avatar
    Join Date
    Nov 2007
    Posts
    431
    You do not need the <cmath> or <string> libraries. You can remove those #includes.

    You can generalize this code by creating a class or struct for denominations of money. Then you could add other denominations such as half dollars or bills by adding only a small amount of new code. Put them in an array or vector and loop through it.

    For example, the loop might look something like this:
    Code:
    for (int i=0; i<denominations.size(); ++i)
    {
        std::cout << cents/denominations[i].value << denominations[i].name << std::endl;
        cents %= denominations[i].value;
    }
    I copied it from the last program in which I passed a parameter, which would have been pre-1989 I guess. - esbo

  11. #11
    Registered User
    Join Date
    Feb 2010
    Posts
    3
    Oops. Not sure why cmath was in there... I don't remember adding it. The string library was placed there when I was going to use string functions to remove the decimal point, but when I decided to go back to ints I forgot to remove it.

    I have turned in the assignment using the rounding trick, but will continue to work on it out of interest. If I have any more questions I'll post them here.

    Thanks!

  12. #12
    Registered User
    Join Date
    Mar 2010
    Posts
    1
    I know this thread is pretty much dead now, but this is how i had to use modulus to break down change in C#.

    //Calculate correct change
    pennies = inputValue;
    quarters = pennies / QUARTER_VAL;
    pennies = pennies % QUARTER_VAL;
    dimes = pennies / DIME_VAL;
    pennies = pennies % DIME_VAL;
    nickels = pennies / NICKEL_VAL;
    pennies = pennies % NICKEL_VAL;

    I used a setup that was originally for calculating hours, minutes and seconds. I'm not sure if I'm following the proper conventions, but it works.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Homework
    By kermi3 in forum A Brief History of Cprogramming.com
    Replies: 11
    Last Post: 11-03-2001, 04:39 PM
  2. Homework
    By kermi3 in forum C Programming
    Replies: 10
    Last Post: 09-27-2001, 04:49 PM
  3. Homework
    By kermi3 in forum C++ Programming
    Replies: 15
    Last Post: 09-26-2001, 03:16 PM
  4. Homework
    By kermi3 in forum Windows Programming
    Replies: 5
    Last Post: 09-15-2001, 11:48 AM
  5. Homework
    By kermi3 in forum C Programming
    Replies: 0
    Last Post: 09-10-2001, 01:26 PM