programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
Sheriffs:
Saloon Keepers:
Bartenders:

Float and Double use in currency

Ranch Hand
Posts: 34

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.

Sheriff
Posts: 3015
12
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.

lowercase baba
Bartender
Posts: 12613
50
• 1
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"

Marshal
Posts: 58449
178
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.

Bartender
Posts: 10575
66

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

Sheriff
Posts: 23451
46
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
Posts: 10575
66

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
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
Sheriff
Posts: 23451
46
• 1
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
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
Posts: 10575
66

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.

Winston

Campbell Ritchie
Marshal
Posts: 58449
178
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
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
Posts: 10575
66

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
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
Posts: 10575
66

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
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
Posts: 10575
66

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"

Sheriff
Posts: 11747
191
• 1

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.

fred rosenberger
lowercase baba
Bartender
Posts: 12613
50

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
Sheriff
Posts: 23451
46

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.