Encyclopaedia Metallum: The Metal Archives

Message board

* FAQ    * Register   * Login 



This topic is locked, you cannot edit posts or make further replies.
Author Message Previous topic | Next topic
MercyfulSatyr
Coelacanthine Cadaver

Joined: Sun Mar 23, 2008 9:22 pm
Posts: 1521
Location: United States
PostPosted: Tue Oct 07, 2008 7:46 pm 
 

For those of you out there who program, you've undoubtedly come across many a frustrating error. So, to aid both veteran and newbie programmers, I've created a thread where you can post your code for others to help debug.

This goes for whatever language you may use; Java, C++, Visual Basic, whatever. If you need some help, there's probably someone here who can help you.

First request:

I'm in a beginners' programming class, and am currently working on a program that is supposed to take a payment and convert it into change, using as few coins and bills as possible. The bills are in increments of 1, 5, 10, and 20, and the coins are quarters, dimes, nickels, and pennies.

I've gotten the bills to work properly, but the coins don't seem to work. For example, if I want to get change for $36.41, which should come out to one of every denomination of coin and bill, I get one of each bill, but no coins.

Here's the code (the important part of it anyway):

double payment = 0.0; //The amount of money paid//
double price = 0.0; //The item's price//

int bill20 = 0; //Amount of $20 bills//
int bill10 = 0; //Amount of $10 bills//
int bill5 = 0; //Amount of $5 bills//
int bill1 = 0; //Amount of $1 bills//
int quarters = 0; //Amount of quarters//
int dimes = 0; //Amount of dimes//
int nickels = 0; //Amount of nickels//
int pennies = 0; //Amount of pennies//

System.out.println("Enter the item's price");
price = console.nextDouble();

System.out.println("Enter amount of money paid");
payment = console.nextDouble();

bill20 = (int) (payment - price) / 20;
bill10 = (int) ((payment - price) - (20 * bill20)) / 10;
bill5 = (int) ((payment - price) - (20 * bill20) - (10 * bill10)) / 5;
bill1 = (int) ((payment - price) - (20 * bill20) - (10 * bill10) - (5 * bill5)) / 1;
quarters = (int) ((payment - price) - (20 * bill20) - (10 * bill10) - (5 * bill5) - bill1) * 4;
dimes = (int) ((payment - price) - (20 * bill20) - (10 * bill10) - (5 * bill5) - bill1 - (quarters / 4)) * 10;
nickels = (int) ((payment - price) - (20 * bill20) - (10 * bill10) - (5 * bill5) - bill1 - (quarters / 4) - (dimes / 10)) * 20;
pennies = (int) ((payment - price) - (20 * bill20) - (10 * bill10) - (5 * bill5) - bill1 - (quarters / 4) - (dimes / 10) - (nickels / 20)) * 100;

System.out.println("Your change is:");
System.out.println(bill20 + " $20 bills");
System.out.println(bill10 + " $10 bills");
System.out.println(bill5 + " $5 bills");
System.out.println(bill1 + " $1 bills");
System.out.println(quarters + " quarters");
System.out.println(dimes + " dimes");
System.out.println(nickels + " nickels");
System.out.println(pennies + " pennies");
_________________
ULTIMATE WINDOWBLADED ARMSAW ATTACK!

caspian wrote:
mercyfulsatyr: easily the most humble man on the board.

My reviews.

Top
 Profile  
Foxx
Metalhead

Joined: Tue Apr 15, 2008 6:59 am
Posts: 823
Location: Australia
PostPosted: Tue Oct 07, 2008 7:50 pm 
 

You're converting your double into an integer and losing the decimal places?

Top
 Profile  
MercyfulSatyr
Coelacanthine Cadaver

Joined: Sun Mar 23, 2008 9:22 pm
Posts: 1521
Location: United States
PostPosted: Tue Oct 07, 2008 8:29 pm 
 

Foxx wrote:
You're converting your double into an integer and losing the decimal places?


I don't know, maybe. I remember that when I didn't typecast the coin values, I got syntax errors and the program wouldn't run.
_________________
ULTIMATE WINDOWBLADED ARMSAW ATTACK!

caspian wrote:
mercyfulsatyr: easily the most humble man on the board.

My reviews.

Top
 Profile  
PeachPit
Metalhead

Joined: Sat Dec 08, 2007 11:52 pm
Posts: 514
Location: Canada
PostPosted: Tue Oct 07, 2008 8:39 pm 
 

MercyfulSatyr wrote:
Foxx wrote:
You're converting your double into an integer and losing the decimal places?


I don't know, maybe. I remember that when I didn't typecast the coin values, I got syntax errors and the program wouldn't run.


Have they taught you modular division? We had to do it in Visual Basic and it wasn't any trouble with modular division.

Modular division is division where the quotient is actually the remainder.

So 123 Mod 25 = 23
So $1.23 Mod $.25 = $.23

Then you modularly divide $.23 by dimes.

EDIT: not even sure if modular division is possible in Java.

Top
 Profile  
MercyfulSatyr
Coelacanthine Cadaver

Joined: Sun Mar 23, 2008 9:22 pm
Posts: 1521
Location: United States
PostPosted: Tue Oct 07, 2008 8:47 pm 
 

PeachPit wrote:
MercyfulSatyr wrote:
Foxx wrote:
You're converting your double into an integer and losing the decimal places?


I don't know, maybe. I remember that when I didn't typecast the coin values, I got syntax errors and the program wouldn't run.


Have they taught you modular division? We had to do it in Visual Basic and it wasn't any trouble with modular division.

Modular division is division where the quotient is actually the remainder.

So 123 Mod 25 = 23
So $1.23 Mod $.25 = $.23

Then you modularly divide $.23 by dimes.

EDIT: not even sure if modular division is possible in Java.


Yeah, we've done that. It didn't seem to work, for some reason.

CL, I know that an integer divided by an integer results in another integer. I should have seen that, though. :durr:

Alright, thanks.
_________________
ULTIMATE WINDOWBLADED ARMSAW ATTACK!

caspian wrote:
mercyfulsatyr: easily the most humble man on the board.

My reviews.

Top
 Profile  
Samapico
Metal newbie

Joined: Wed Aug 11, 2004 8:51 pm
Posts: 253
Location: Canada
PostPosted: Tue Oct 07, 2008 10:51 pm 
 

Quote:
EDIT: not even sure if modular division is possible in Java.
Modulo is a very common operation available in all languages. In C/C++ it's done with the % operator, java might be the same, I don't know.


I suggest you substract values from the payment after each bill number you calculate. That way, you avoid repeating operations such as ((payment - price) - (20 * bill20))
And if you don't want to work with doubles, you could process the integer part and the fractional part separately. Not only will you avoid countless casting, integer calculations are much faster than with doubles.

Generally, whenever you see a formula that you have to put at several places, it's better to use a variable with the result, so the program only has to compute the result once.

Code:
double balance = payment - price;

int dollars = (int)balance; // Cut the decimals
int cents   = balance * 100.0 - dollars; //Maybe Java has a fpart() function or something that could work better, I don't know

bill20 = dollars / 20; 

dollars -= bill20 * 20; //Remove the dollars we counted

bill10 = dollars / 10;

dollars -= bill10 * 10;

// ...
//Repeat for each bills, and when you arrive at the cents, repeat the same process starting with 'cents' instead of 'dollars'
_________________
Subspace / Continuum - "Meet people from all over the world... then kill 'em."
Longest-running MMO action game... It's totally free too. And addicting.

Top
 Profile  
Exmachete
Metal newbie

Joined: Sat Mar 03, 2007 3:51 am
Posts: 62
Location: Australia
PostPosted: Wed Oct 08, 2008 12:13 am 
 

Modulo is done with a % in Java just as it is in C/C++ - Java heavily borrowed its syntax from C/C++.
_________________
oVerCaffeinated wrote:
... When donating blood, don't be a pussy and just ask for a hand gun and a bucket.

Top
 Profile  
Krelgen
Metal newbie

Joined: Sun Mar 30, 2008 11:23 pm
Posts: 56
Location: United States of America
PostPosted: Wed Oct 08, 2008 12:28 am 
 

Personally I'd take an approach involving arrays.

You can cut out decimal calculations by converting dollar amounts into pennies, which can be stored as an integer. Be sure to pay very close attention to any decimal-to-integer conversions. Direct assignments, conversions or typecasting may drop certain decimal places. Other unforeseen problems may occur as well.

Here's my method. Could be some improvements, my decimal conversion is a really bad attempt, many values will not convert properly. But for all practical purposes, the example still shows how the core task can be accomplished.
Code:
   //Array of currency denominations, from largest to smallest (in pennies)
   int Denom[] = {2000, 1000, 500, 100, 25, 10, 5, 1};

   //Display text for plural amounts
   char *DenomStrPl[] = {"$20 bills", "$10 bills", "$5 bills", "$1 bills", "quarters", "dimes", "nickels", "pennies"};

   //Display text for singular amounts (woohoo, fancy stuff)
   char *DenomStrSi[] = {"$20 bill", "$10 bill", "$5 bill", "$1 bill", "quarter", "dime", "nickel", "penny"};

   //Note: all 3 arrays should line up with corresponding values

   int count = 0;     //Number of counts for each current denomination of money
   int curindex = 0;  //Index of the starting denomination type

   //Substitute whatever amount here, and convert it to pennies.
   //Overall this is a pretty bad way of doing it, it won't work for all decimal values.
   double price = 36.41;
   int amount = (int) ceil(price * 100);

   //Just a quick display to see if the value was converted properly
   //If you do any conversions, you might want to output something
   //like this just to make sure it worked.
   printf("$%g = %d pennies \n", price, amount);
   
   //If it checks (amount > 0) then it won't output the final penny count
   while (amount >= 0)
   {
      if(amount >= Denom[curindex])
      {
         //The current amount contains enough money for that denomination, so subtract
         //it from the remaining value and increment the counter
         amount -= Denom[curindex];
         count++;
      }
      else
      {
         //Amount left is less than the current denomination requires

         //If the count is only one, output the singular text.
         //If greater than 1, output the plural text.
         //If zero, nothing will be printed
         if(count == 1)
            printf("%d %s (%d pennies left)\n", count, DenomStrSi[curindex], amount);
         else if (count > 1)
            printf("%d %s (%d pennies left)\n", count, DenomStrPl[curindex], amount);

         //Increment the index to the next size denomination, and reset
         //the count for a fresh start.
         curindex++;
         count = 0;
      }
   }


Output:
Code:
$36.41 = 3641 pennies
1 $20 bill (1641 pennies left)
1 $10 bill (641 pennies left)
1 $5 bill (141 pennies left)
1 $1 bill (41 pennies left)
1 quarter (16 pennies left)
1 dime (6 pennies left)
1 nickel (1 pennies left)
1 penny (0 pennies left)

Top
 Profile  
MercyfulSatyr
Coelacanthine Cadaver

Joined: Sun Mar 23, 2008 9:22 pm
Posts: 1521
Location: United States
PostPosted: Wed Oct 08, 2008 3:42 pm 
 

Samapico wrote:
Quote:
EDIT: not even sure if modular division is possible in Java.
Modulo is a very common operation available in all languages. In C/C++ it's done with the % operator, java might be the same, I don't know.


I suggest you substract values from the payment after each bill number you calculate. That way, you avoid repeating operations such as ((payment - price) - (20 * bill20))
And if you don't want to work with doubles, you could process the integer part and the fractional part separately. Not only will you avoid countless casting, integer calculations are much faster than with doubles.

Generally, whenever you see a formula that you have to put at several places, it's better to use a variable with the result, so the program only has to compute the result once.

Code:
double balance = payment - price;

int dollars = (int)balance; // Cut the decimals
int cents   = balance * 100.0 - dollars; //Maybe Java has a fpart() function or something that could work better, I don't know

bill20 = dollars / 20; 

dollars -= bill20 * 20; //Remove the dollars we counted

bill10 = dollars / 10;

dollars -= bill10 * 10;

// ...
//Repeat for each bills, and when you arrive at the cents, repeat the same process starting with 'cents' instead of 'dollars'


Heh, we learned how to do that last part today. Nice timing. :lol:

Alright, I've got the program to work now. Thanks, everyone.

Let's see some other issues. This thread wasn't just for me, you know!
_________________
ULTIMATE WINDOWBLADED ARMSAW ATTACK!

caspian wrote:
mercyfulsatyr: easily the most humble man on the board.

My reviews.

Top
 Profile  
Samapico
Metal newbie

Joined: Wed Aug 11, 2004 8:51 pm
Posts: 253
Location: Canada
PostPosted: Wed Oct 08, 2008 3:55 pm 
 

Krelgen wrote:
Personally I'd take an approach involving arrays.
Yeah, I'd do that too, but I thought it might be a lot of new concepts for him at the same time :P
But yeah, that array thing would be the next step of improvement ;)
_________________
Subspace / Continuum - "Meet people from all over the world... then kill 'em."
Longest-running MMO action game... It's totally free too. And addicting.

Top
 Profile  
Krelgen
Metal newbie

Joined: Sun Mar 30, 2008 11:23 pm
Posts: 56
Location: United States of America
PostPosted: Wed Oct 08, 2008 10:57 pm 
 

Samapico wrote:
Krelgen wrote:
Personally I'd take an approach involving arrays.
Yeah, I'd do that too, but I thought it might be a lot of new concepts for him at the same time :P
But yeah, that array thing would be the next step of improvement ;)


Heh, I originally thought the same, but you never know. Never hurts to try for a little extra credit. Still, if his class hasn't covered arrays yet, this introduction might give a head start.

Anyway, to the original poster:
I realized I should probably take the time to go back and look at the specific error in your code. Although I'm working with a C++ compiler, the syntax is pretty much the same.

Your error was caused by improper typecasting, which can be fixed by adding another set of parentheses. I'll try to simplify the following line into the data types being used, to help illustrate what I'm trying to explain.

bill10 = (int) ((payment - price) - (20 * bill20)) / 10;
int = (int) ((double - double) - (int * int)) / int;
int = (int) (double - int) / int;
int = int / int;

The problem is that (int) typecast works against (double - int), which results in integer division, and therefore does not consider decimals in the equation. This can be fixed by enclosing all mathematical operations in another set of parenthesis.
bill10 = (int) ( ((payment - price) - (20 * bill20)) / 10 );

Typecasting should always be applied whenever that specific conversion is needed. Consider the following code. Even though C is of type double, it still involves division between integer types and may not produce the expected result.

int A = 5;
int B = 10;
double C = A / B;

Four typecasting scenarios are possible:
double C = A / B; //evaluates to 0
double C = (double)A / B; //evaluates to 0.5
double C = A / (double)B; //evaluates to 0.5
double C = (double)A / (double)B; //evaluates to 0.5

Although both 2 and 3 give the same result as 4, I normally choose to write things out as the 4th option. I find this easier to understand, and avoids the problem of having to make any assumptions about its intended behavior.

Top
 Profile  
Corimngul
Freddled Gruntbuggly

Joined: Tue Apr 20, 2004 12:18 pm
Posts: 872
Location: Sweden
PostPosted: Mon Nov 03, 2008 2:34 am 
 

Anybody know of some good library for real-time graphing in java or should I cook something up using lists of polygons?
_________________
Wra1th1s wrote:
When I meant EVERY black metal band of course I don't mean EVERY black metal band.
Montmirail wrote:
Because I hate ID 100369. Numbers 19, 29, 39, 49, 59 are incomplete and I hate it!

Top
 Profile  
Chaos_Llama
Metalhead

Joined: Fri Mar 07, 2008 7:04 pm
Posts: 410
Location: United States
PostPosted: Mon Nov 03, 2008 2:54 am 
 

How dynamic does it have to be? For work this summer I used [url]http://www.jfree.org/jfreechart/]JFreeChart[/url] and there are a multitude of other libraries to be found (such as JGraph) that you can tweak to do what you want. All the really good stuff will cost you money. (JFreeChart you will have to figure out from the API, developer's guide costs money).

Top
 Profile  
Corimngul
Freddled Gruntbuggly

Joined: Tue Apr 20, 2004 12:18 pm
Posts: 872
Location: Sweden
PostPosted: Mon Nov 03, 2008 4:48 pm 
 

Ah, that may be good enough. It doesn't really need to be that dynamic. A five second update interval will cut it.
_________________
Wra1th1s wrote:
When I meant EVERY black metal band of course I don't mean EVERY black metal band.
Montmirail wrote:
Because I hate ID 100369. Numbers 19, 29, 39, 49, 59 are incomplete and I hate it!

Top
 Profile  
Display posts from previous:  Sort by  
This topic is locked, you cannot edit posts or make further replies.


Who is online

Users browsing this forum: No registered users and 19 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

 
Jump to:  

Back to the Encyclopaedia Metallum


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group