File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Float and Double use in currency Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Float and Double use in currency" Watch "Float and Double use in currency" New topic
Author

Float and Double use in currency

Greg Ferguson
Ranch Hand

Joined: Jun 04, 2012
Posts: 34
I apologize in advance if this has already been addressed.

I am currently working on a project that involves the use of numbers as currency. It seems a lot of people discourage using the float or double data types to represent money. Instead they suggest using int, long, or BigDecimal. Now, I'm familiar with int and long, but I never knew BigDecimal even existed ... until today.

So my questions are:
What is the general consensus about using float or decimal to represent money?
How can I use Integer or Long to represent money?
Should I even attempt to use BigDecimal as a beginner?

Thanks.
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2771
    
  10

Probably, Integer, Long, or BigInteger, right? The idea is that instead of representing, say, US dollars in a floating point, you represent US cents in an integer. Integer arithmetic is faster and not subject to rounding errors ... except with division. You have to understand your requirements though. Sometimes a float or double may be what you want.

Also, you're working with amounts too high to fit in a Long, let me know. I want to work there.
fred rosenberger
lowercase baba
Bartender

Joined: Oct 02, 2003
Posts: 10916
    
  12

money only exists in discrete amounts. Sure, we say you can have 1.47 dollars...but that is really 147 pennies - an integer amount. Every currency has some base unit that you can't have a fraction of...Therefore, it makes sense to use something that handles discrete amounts.

And as Greg said, using floating point variables will lead to rounding error. if you add 0.01 together enough times, eventually you'll start seeing extra pennies added in, because 0.01 is actually stored as something like "0.0100000000000324"


There are only two hard things in computer science: cache invalidation, naming things, and off-by-one errors
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 36508
    
  16
It is not that hard to learn to use BigDecimal; even I managed to do it. (Scroll to the bottom of that discussion for a bit more information). You can find out the exact value of 0.1, and a warning not to use it, here.

Once you know how to use BigDecimal, you will never feel the temptation to use floating‑point arithmetic for money again.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7063
    
  16

fred rosenberger wrote:money only exists in discrete amounts.

That's one of the best and most succinct explanations I've ever come across, Fred. And of course, absolutely right. Well done. Gold star from me.

'Course, then you get accountants; and bosses...and of course governments have to stick their oar in....

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Artlicles by Winston can be found here
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18135
    
    8

Yes, money exists in discrete amounts -- but often the real world has particular rounding rules which must be used when a calculation results in a number which isn't one of those discrete amounts. These typically apply after you calculate a certain percentage of a money amount and tell you what to do with the fractional cents which result. Sometimes it's plain old half-up rounding and sometimes there are other rules. For example I've worked with a government-mandated rule which says that you truncate the result (in cents) to 1 decimal place, then round up everything which isn't an exact number of cents to the next higher cent.

So it's quite likely you will have to deal with this sort of thing in your application.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7063
    
  16

Paul Clapham wrote:Yes, money exists in discrete amounts -- but often the real world has particular rounding rules which must be used when a calculation results in a number which isn't one of those discrete amounts.

Yes, but unless you understand the basic premise, you'll never get the rest.

For example I've worked with a government-mandated rule which says that you truncate the result (in cents) to 1 decimal place, then round up everything which isn't an exact number of cents to the next higher cent.

And has anybody challenged this? Sometimes I think they bring in these rules just to see if we're still awake. Either that, or it's jobs for the boys. What about penny shaving? I've actually come across a rule that would theoretically make it legal, but was the gov interested? Nah: these are them, until someone much higher up than you tells us otherwise.

Our taxes, my friend. And in most cases KISS works best.

Winston
Greg Ferguson
Ranch Hand

Joined: Jun 04, 2012
Posts: 34
Thanks for all of your replies and suggestions. I decided to look more into the use of BigDecimal and realized that it wasn't as confusing as I first thought. I decided to use it in my project and the results are just what I hoped. Since I'm so far ahead in the class, I'm not going to post the working code for the hardest parts of this project. I have posted the code for the easier part though just to show one of the ways I'm using BigDecimal. The part I'm not posting involves breaking down the displayed amount into $1 bills, quarters, dimes, nickels, and pennies to get the least amount of change.

I would like some suggestions on whether or not I could have coded this with less lines or if you see anything redundant or useless; I appreciate your feedback. Thanks.

Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18135
    
    8

These three lines:



Read the API documentation for the BigDecimal constructor "BigDecimal(double)", and then rewrite them with code which works better and has one fewer line.
Greg Ferguson
Ranch Hand

Joined: Jun 04, 2012
Posts: 34
Thanks for pointing that out Paul. I think I understand what you were saying. I rewrote the code and eliminated two lines from the previous code I posted, here's the revision.

I guess I didn't need to use double at all.

Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7063
    
  16

Buenny Fry wrote:I rewrote the code and eliminated two lines from the previous code I posted, here's the revision.

I guess I didn't need to use double at all.

Nope. And well done. A good lesson learned.

You may be interested in reading this page now. It's often just called 'Goldberg', because it's linked to so often .

Winston
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 36508
    
  16
If you are using a Scanner, you don’t need the text, nor the valueOf method. You can use nextBigDecimal().

And well done sorting out the rest of the arithmetic
Greg Ferguson
Ranch Hand

Joined: Jun 04, 2012
Posts: 34
Campbell Ritchie wrote:If you are using a Scanner, you don’t need the text, nor the valueOf method. You can use nextBigDecimal().

And well done sorting out the rest of the arithmetic


I realized that in my quest to see if I could write less code, and thanks.

I have really revised and added to the code. I was trying to find a way to catch input errors. For the most part, I get the desired results but the small issue I'm having is whenever input for the second Scanner isn't a number, the error is caught but instead of being able to reenter a value it just restarts. Is there a way I can loop back to the second Scanner instead of the beginning? I hope that makes sense.

Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7063
    
  16

Buenny Fry wrote:I have really revised and added to the code....

Buenny,

I've split up the very long lines in your code. Please re-read the UseCodeTags page, as it explains why not to use them.

Thanks.

Winston
Greg Ferguson
Ranch Hand

Joined: Jun 04, 2012
Posts: 34
Winston Gutkowski wrote:
Buenny Fry wrote:I have really revised and added to the code....

Buenny,

I've split up the very long lines in your code. Please re-read the UseCodeTags page, as it explains why not to use them.

Thanks.

Winston


Thank you. I didn't mean to get carried away like that. I cut it way down to make my issue more relevant.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7063
    
  16

Buenny Fry wrote:Is there a way I can loop back to the second Scanner instead of the beginning? I hope that makes sense.

Very much so. Personally, I find Scanner quite tricky (and often counter-intuitive), despite the fact that it was supposed to "make things easier".

My "lazy man's" tip:
1. Use nextLine() to get the user's input, as this requires them to hit the ENTER key.
2. Once you have the String (the input line), use your 2nd Scanner (see new Scanner(String)) to validate the input (or alternatively, new BigInteger(String), inside a try...catch block).
NOTE: You may want to trim() the string before you parse it.

The nice thing about this approach is that it lends itself to most forms of streamed input, including passing the input in via a text file.

Also: try to avoid things like while(true) if you can (which is essentially what your outer loop is). One possibility is:
HIH

Winston
Greg Ferguson
Ranch Hand

Joined: Jun 04, 2012
Posts: 34
Winston Gutkowski wrote:

Also: try to avoid things like while(true) if you can (which is essentially what your outer loop is). One possibility is:
HIH

Winston


Thanks for the suggestions. I was able to make it work, but now I don't know how to terminate the loop since the use of "break" is discouraged. How can I make getAmtTend.hasNextLine false?
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7063
    
  16

Buenny Fry wrote:but now I don't know how to terminate the loop since the use of "break" is discouraged.

Who said that? Send 'em here and I'll shoot 'em for you.

How can I make getAmtTend.hasNextLine false?

Well, if you've already got a line and you're using:
getAmtTend = new Scanner(line);
as I suggested, you should be able to get the value with:
BigInteger amtTend = getAmtTend.nextBigInteger();
Just be aware that it can throw an Exception if the value entered is invalid (or you can use hasNextBigInteger()).

And BTW, it is true that you can avoid a break by adding extra conditions to the loop; but it's often more bother than it's worth.

You may also want to consider a separate loop for each value to enter.

Winston "Shoot first and ask questions later"
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4419
    
    5

Making your code more composed will help you work out the logic better.

Once you have the overall solution story "told" like this, it's easier to wrap your head around the solution for the smaller problems.

Edit: the above code can be made even less wordy if you can establish that you're dealing with amounts in general:


With the surrounding code providing enough context, you can drop the "amount" prefix on variables to remove redundancy, in line with the DRY principle (Don't Repeat Yourself), which I also take to the conceptual level.


Junilu - [How to Ask Questions] [How to Answer Questions]
fred rosenberger
lowercase baba
Bartender

Joined: Oct 02, 2003
Posts: 10916
    
  12

Paul Clapham wrote:Yes, money exists in discrete amounts -- but often the real world has particular rounding rules which must be used when a calculation results in a number which isn't one of those discrete amounts.

I would argue that no matter what the rules for 'figuring out the amount', you would want to store it as an integer type.

But that is just my opinion...
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18135
    
    8

fred rosenberger wrote:
Paul Clapham wrote:Yes, money exists in discrete amounts -- but often the real world has particular rounding rules which must be used when a calculation results in a number which isn't one of those discrete amounts.

I would argue that no matter what the rules for 'figuring out the amount', you would want to store it as an integer type.


Yes, I agree. I was just trying to point out that the intermediate calculations could involve non-integer values.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Float and Double use in currency
 
Similar Threads
Explain me .
how to check if a double is exact multiple of an increment value
Money value object
Bad Double
Precision loss in String to Float and double to float