473,386 Members | 1,654 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Counting change

I'm brand new to C++, yet I have experience in many other languages. This script I wrote prompts the user for a change amount, then calculates the amounts of each coin that amount is. For example, 37 cents is 1 quarter, 1 dime, and 2 pennies. I have a while loop but it keeps looping when it shouldn't

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4.     double input=0.00;
  5.     int quarters=0;
  6.     int pennies=0;
  7.     int dimes=0;
  8.     int nickels=0;
  9.     cout<<"Enter the amount you wish to convert: ";
  10.     cin>>input;
  11.     do{
  12.         if(input>0.25){
  13.             quarters++;
  14.             input-=0.25;
  15.         }    
  16.         else if(input>0.10){
  17.             dimes++;
  18.             input-=0.10;
  19.         }
  20.         else if(input>0.05){
  21.             nickels++;
  22.             input-=0.05;
  23.         }
  24.         else if(input>0.01){
  25.             pennies++;
  26.             input-=0.01;
  27.         }
  28.     }while(input>0.00);
  29.     cout<<"\n"<<quarters<<" quarters, "<<dimes<<" dimes, "<<nickels<<" nickels, and "<<pennies<<" pennies.\n";
  30. }
Feb 18 '08 #1
12 2823
gpraghuram
1,275 Expert 1GB
I'm brand new to C++, yet I have experience in many other languages. This script I wrote prompts the user for a change amount, then calculates the amounts of each coin that amount is. For example, 37 cents is 1 quarter, 1 dime, and 2 pennies. I have a while loop but it keeps looping when it shouldn't

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4.     double input=0.00;
  5.     int quarters=0;
  6.     int pennies=0;
  7.     int dimes=0;
  8.     int nickels=0;
  9.     cout<<"Enter the amount you wish to convert: ";
  10.     cin>>input;
  11.     do{
  12.         if(input>0.25){
  13.             quarters++;
  14.             input-=0.25;
  15.         }    
  16.         else if(input>0.10){
  17.             dimes++;
  18.             input-=0.10;
  19.         }
  20.         else if(input>0.05){
  21.             nickels++;
  22.             input-=0.05;
  23.         }
  24.         else if(input>0.01){
  25.             pennies++;
  26.             input-=0.01;
  27.         }
  28.     }while(input>0.00);
  29.     cout<<"\n"<<quarters<<" quarters, "<<dimes<<" dimes, "<<nickels<<" nickels, and "<<pennies<<" pennies.\n";
  30. }

It is always advisable not to use double values for checking in loop.
My idea is convert the double into integer value by multiplying bu 100 and then check it as integer value


Raghuram
Feb 18 '08 #2
Your problem's a bit obvious if you run a test and watch the value of input.
If you do you'll notice it stays stuck at 0.01.

I'll explain it with his example:
37 this means that input = 37;
now 25 gets deducted for a quarter so 12 is left.
now 10 gets deducted for a dime so 2 is left.
And now a penny gets deducted so input = 0.01.

There problem is with your test, input = 0.01 but you test for > so you need to replace your > with >= and it'll work.

And a question about your program, doesn't a quarter = 25 cents?
Because in your program you deduct 0.25 cents so you'll get about 140ish quarters for 37.
Feb 18 '08 #3
Banfa
9,065 Expert Mod 8TB
And a question about your program, doesn't a quarter = 25 cents?
Because in your program you deduct 0.25 cents so you'll get about 140ish quarters for 37.
Not if the input is in dollars :-)

However the final test against 0.00 in the while loop is a problem. As gpraghuram says using a float or double variable to test for a logical condition is nearly always a bad idea because these variable types only hold an approximation which means that some of the least significant decimal places may not hold the value you are expecting but these places do effect the logical outcome.

In my opinion it would be better to convert the input from dollars to cents to start with which can be held in an integer value and then do your calculations in cents with the more precise mathematics that integers provide

Expand|Select|Wrap|Line Numbers
  1.     double input=0.00;
  2.     int input_as_cents;
  3.  
  4. ...
  5.  
  6.     cout<<"Enter the amount you wish to convert: ";
  7.     cin>>input;
  8.  
  9.     input_as_cents = static_cast<int>(input*100+0.5);   
  10.  
Feb 18 '08 #4
True, but his first post says: 37 cents is 1 quarter, 1 dime, and 2 pennies.
So I assume he's talking about entering an ammount of cents which would eliminate the need for a double.
And I don't really count bills as change.
Feb 18 '08 #5
weaknessforcats
9,208 Expert Mod 8TB
The fundamental error here is using floating point for money because of that cute little decimal point. Unfortunately, using floating point incurs rounding so all of your comparisons are off. There are actual laws in Europe prohibiting the use of floating point in finance calculations.

Use integers only and keep the amounts in pennies. That is a quarter is 25. A dollar is 100.

A integer containing 12345 can be passed to a function that displays it as $123.45.
Feb 18 '08 #6
Sorry if I wasn't clear in my description. This isn't necessarily a program that I will use when I'm at a restaurant, it's just something simple to try out. I just wanted to take a shot at C++. Anyway, thanks for all your help, my program works now.

Thanks,
Jordan
Feb 18 '08 #7
whodgson
542 512MB
Assuming you implement the suggestions by 'weaknessforcats' isn`t it necessary to divide by 25 as well as mod by 25?
If the input was say (int) 87, 87/25 = 3 to be saved as quarters and 87%25 = 12 which would become the new input for dimes. Now repeat for nickles and thence obtain remainder in cents.
Also don`t you need to cover the possibility of input being < 25 and > 10?;so that 0 quarters will be recorded.
Feb 19 '08 #8
Banfa
9,065 Expert Mod 8TB
Assuming you implement the suggestions by 'weaknessforcats' isn`t it necessary to divide by 25 as well as mod by 25?
If the input was say (int) 87, 87/25 = 3 to be saved as quarters and 87%25 = 12 which would become the new input for dimes. Now repeat for nickles and thence obtain remainder in cents.
Also don`t you need to cover the possibility of input being < 25 and > 10?;so that 0 quarters will be recorded.
Actually because of the construction of the program using a while loop all of these cases are handled. Each time round the loop a single coin is accounted for.

Using the maths you suggest would make it possible to eliminate the while loop but in it self the program is (or at least does look) functional.
Feb 19 '08 #9
Banfa
9,065 Expert Mod 8TB
Sorry if I wasn't clear in my description. This isn't necessarily a program that I will use when I'm at a restaurant, it's just something simple to try out. I just wanted to take a shot at C++. Anyway, thanks for all your help, my program works now.
:D you don't need to apologise all the comments here are made entirely in respect of the code you posted and our suggestions for fixing any errors and improving it and generally suggestion methods of avoiding pitfalls in the future.

Most experienced programmers know that floating points and a thing to be used really only for calculation and output of values not control of program logic because the the errors introduced by rounding because floating point types hold approximations to numbers.

Look at this example

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <iomanip>
  3.  
  4. using namespace std;
  5.  
  6. static const float  TEST_VALUE  = 1234567800.0F;
  7. static const int    MAX_LOOP    = 100;
  8.  
  9. int main()
  10. {
  11.     float f1 = TEST_VALUE;
  12.     float f2 = TEST_VALUE;
  13.     int ix;
  14.  
  15.     for(ix=0; ix<MAX_LOOP; ix++)
  16.     {
  17.         f2 -= TEST_VALUE/MAX_LOOP;
  18.     }
  19.  
  20.     f1 -= TEST_VALUE;
  21.  
  22.     // At this point f1 and f2 should be 0.0
  23.     // f1 has had the entire value taken away
  24.     // f2 has had 100 times 1/100 of the value taken away
  25.  
  26.     cout << "f1: " << f1 << " : == 0 - " << ((f1==0.0)?"true":"false") << endl;
  27.     cout << "f2: " << f1 << " : == 0 - " << ((f2==0.0)?"true":"false") << endl;
  28.  
  29.     return 0;
  30. }
On my compiler (MS VisualStudio 2005) the output is
Expand|Select|Wrap|Line Numbers
  1. f1: 0 : == 0 - true
  2. f2: 229.92 : == 0 - false
  3.  
Mathematically both values should be 0 (because X - 100 * (X / 100) == X - X == 0) f2 is not equal to 0 because of the rounding errors introduce in doing the calculation in that manor.

There actually are ways to compensate for rounding errors when taking small floating point numbers away from large ones for example the Kahan summation algorithm. If I implement this algorithm in my program it becomes

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <iomanip>
  3.  
  4. using namespace std;
  5.  
  6. static const float  TEST_VALUE  = 1234567800.0F;
  7. static const int    MAX_LOOP    = 100;
  8.  
  9. int main()
  10. {
  11.     float f1 = TEST_VALUE;
  12.     float f2 = TEST_VALUE;
  13.     float t,y,c;
  14.     int ix;
  15.  
  16.     c = 0.0;
  17.     for(ix=0; ix<MAX_LOOP; ix++)
  18.     {
  19.         y = (-TEST_VALUE/MAX_LOOP) - c;
  20.         t = f2 + y;
  21.         c = (t - f2) - y;
  22.         f2 = t;
  23.     }
  24.  
  25.     f1 -= TEST_VALUE;
  26.  
  27.     // At this point f1 and f2 should be 0.0
  28.     // f1 has had the entire value taken away
  29.     // f2 has had 100 times 1/100 of the value taken away
  30.  
  31.     cout << "f1: " << f1 << " : == 0 - " << ((f1==0.0)?"true":"false") << endl;
  32.     cout << "f2: " << f2 << " : == 0 - " << ((f2==0.0)?"true":"false") << endl;
  33.  
  34.     return 0;
  35. }
and the output is

Expand|Select|Wrap|Line Numbers
  1. f1: 0 : == 0 - true
  2. f2: 8 : == 0 - false
  3.  
f2 has still not reached 0 but it is a lot closer to the correct value. What has happen is that in each iteration of the loop the variable c has been used to carry the loss of precision (rounding error) in taking a large number away from a small number forward to the next iteration so that it may be included there.
Feb 19 '08 #10
weaknessforcats
9,208 Expert Mod 8TB
At some point I hope you will start using integers for accounting aapplications and avoid all this trouble.

I say again, keep your amounts in pennies. In integers.
Feb 19 '08 #11
Banfa
9,065 Expert Mod 8TB
I say again, keep your amounts in pennies. In integers.
Perhaps I should iterate that I agree on this point, I was just waxing lyrical on the problems of floating point arithmatic and some of the ways of mitigating it in general.

In fact you could go a stage further and say that not only for currency but for many situations where you are only interesting in a few decimal places and not extremely large numbers you should consider using integers over floating point numbers.
Feb 19 '08 #12
weaknessforcats
9,208 Expert Mod 8TB
Yes, indeed. For everything, in fact.

As I understand it, floating point came into being to support scientific research where extreme accuracy is often not required. So, unless you are doing some of this research, you should be using integers throughout. Then, if you do use floating point, use only double.
Feb 20 '08 #13

Sign in to post your reply or Sign up for a free account.

Similar topics

6
by: Elbert Lev | last post by:
Please correct me if I'm wrong. Python (as I understand) uses reference counting to determine when to delete the object. As soon as the object goes out of the scope it is deleted. Python does...
3
by: Viswanatha Thalakola | last post by:
Hello, Can someone point me to getting the total number of inserts and updates on a table over a period of time? I just want to measure the insert and update activity on the tables. Thanks....
8
by: DrNoose | last post by:
Hi! I'm writing a program that is supposed to read a line of input, count the words and the number of occurrences of each letter. Then it should prints the number of occurrences of each letter...
4
by: Chad Reid | last post by:
Hello, I have a bit of code that obviously doesn't work, but I need help creating a query that would have the same effect as if this query was working. SELECT * FROM (SELECT Count(*) AS...
4
by: Alicia | last post by:
I am having a problem grouping by week. I am looking for the simpliest way of doing it in Microsoft Access. I have tried to use a pre-loaded calender, access did not like it at all. If there is...
18
by: ChadDiesel | last post by:
I appreciate the help on this group. I know I've posted a lot here the last couple of weeks, but I was thrown into a database project at my work with very little Access experience. No other...
7
by: sathyashrayan | last post by:
Group, Following function will check weather a bit is set in the given variouble x. int bit_count(long x) { int n = 0; /* ** The loop will execute once for each bit of x set,
1
by: j | last post by:
Hi, I've been trying to do line/character counts on documents that are being uploaded. As well as the "counting" I also have to remove certain sections from the file. So, firstly I was working...
5
by: andy.lee23 | last post by:
hi im having trouble counting lines in a text file, i have the following code int node1, node2, i; char name; float value; ifstream fin; fin.open(OpenDialog1->FileName.c_str()); i=1;
4
by: aaronfude | last post by:
Hi, Please consider the following class (it's not really my class, but it's a good example for my question): class Vector { int myN; double *myX; Vector(int n) : myN(n), myX(new double) { }...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.