Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!

# Money and digits problem

Tyson Lindner
Ranch Hand
Posts: 211
I'm writing a program that does some simple math problems on user inputted dollar amounts. I'm currently using double for those amounts.

Sometimes, the user might enter 7.25 and 2.20, in which case, if its subtraction I need my output to be 5.05, but for larger numbers like 15,000 and 3000 I want my output to be "12,000" not "12,000.00". Is there an easy way around this or would I have to check my numbers and adjust the format every time?

fred rosenberger
lowercase baba
Bartender
Posts: 12127
30
• 1
Tyson Lindner wrote:I'm writing a program that does some simple math problems on user inputted dollar amounts. I'm currently using double for those amounts.

That is a mistake. Money comes in discrete units, therefore you should use an integer type. In the U.S., the atomic unit would be cents, so the user input should be converted to pennies and all computations done that way with integer arithmetic. Otherwise, you will start finding weird rounding errors.

Paul Clapham
Sheriff
Posts: 21107
32
As for the formatting of "larger" versus "non-larger" numbers: Yes, you're going to have to write code which says "If X is a larger number then format it this way, otherwise format it that way".

Pat Farrell
Rancher
Posts: 4678
7
Never use float or double for money. Store the integer number of pennies. This works for US, Canadian, Austrailian, etc. dollars, Euros and other kinds of money.

Then use Formats to add or remove the decimal points into the right places.

Tyson Lindner
Ranch Hand
Posts: 211
Thanks for the replies, i'll definitely convert to int but just a quick follow up question:

The user input will still be double, is there a way to check how specific the input is? That way if the user puts in "125" I can have one print format, if its "125.75" I can have another, and if its "125.12352" I can print an error message.

I think I'll just scrap the idea of format depending on the size of the number, I don't really care if large numbers have the decimal places if that's how the user inputted them.

Pat Farrell
Rancher
Posts: 4678
7
Tyson Lindner wrote:The user input will still be double, is there a way to check how specific the input is? That way if the user puts in "125" I can have one print format, if its "125.75" I can have another, and if its "125.12352" I can print an error message.

No! The user input is not double. The user input is a String. its a String that may have look like: "125.12" or "125.12352"
It is never a double. The user input may also look like "12S.L2" where there is an S and a L instead of the proper digits 5 and 1 (one). It can look like "125.12 125.12"

You have to process/parse the user's input, see if it makes sense, and use it or give an error message.

Tyson Lindner
Ranch Hand
Posts: 211
Pat Farrell wrote:
Tyson Lindner wrote:The user input will still be double, is there a way to check how specific the input is? That way if the user puts in "125" I can have one print format, if its "125.75" I can have another, and if its "125.12352" I can print an error message.

No! The user input is not double. The user input is a String. its a String that may have look like: "125.12" or "125.12352"
It is never a double. The user input may also look like "12S.L2" where there is an S and a L instead of the proper digits 5 and 1 (one). It can look like "125.12 125.12"

You have to process/parse the user's input, see if it makes sense, and use it or give an error message.

Yeah I was parsing the string using Double.parseDouble() and catching a NumberFormatException, but 12.24523 is bad input for my purposes but won't throw an exception, so I'm wondering how I catch that.

Bear Bibeault
Author and ninkuma
Marshal
Posts: 64858
86
I'll second Pat on that. For no purposes at all should double or float ever be used for money. Ever.

Pat Farrell
Rancher
Posts: 4678
7
Tyson Lindner wrote:Yeah I was parsing the string using Double.parseDouble() and catching a NumberFormatException, but 12.24523 is bad input for my purposes but won't throw an exception, so I'm wondering how I catch that.

Very bad to parse with .parseDouble(), as you'll be tempted to use the result. Plus, as you say, it doesn't catch a number of frequently occurring real world errors.

The standard approach is to use the Pattern and Matcher classes to process a regular expression. This also allows you to accept and ignore commas in the number. Sadly, its a bit complex to get the regex exactly right, you can get it close with a few minutes of effort, but getting it exact for all cases is a lot of effort.

Tyson Lindner
Ranch Hand
Posts: 211
Jeff Verdegan wrote:
Pat Farrell wrote:Never use float or double for money.

I don't think that will work. I don't think you can use the formatting tools in the core API to add decimal points to integers. You'd have to roll your own, I believe.

Yeah I'm currently trying to figure this out. I can convert the double to int, but now I'm having trouble finding a way to print the integer back out with decimal places (if needed) in a JLabel. I suppose I can convert back to double and figure out how formatting works for JLabel which is something I was going to have to do anyway.

Jeff Verdegan
Bartender
Posts: 6109
6
Tyson Lindner wrote:
Jeff Verdegan wrote:
Pat Farrell wrote:Never use float or double for money.

I don't think that will work. I don't think you can use the formatting tools in the core API to add decimal points to integers. You'd have to roll your own, I believe.

Yeah I'm currently trying to figure this out. I can convert the double to int,

You won't convert double to int. If you take that approach, you'll only use int (or long). You'll never use double at all. Instead of storing and calculating in dollars, you'll do it in pennies. Then, when you want to display it in dollars, you'll have to convert your int to a String, and insert a decimal point before the last two digits (and also insert a leading zero if the int value is less than 10). [EDIT: Or use format() as Pat shows a couple posts further down. I had a total brain f**t thinking we couldn't do that. It's cleaner that way, but make sure you understand what it's doing and why it works if you decide to use it.]

but now I'm having trouble finding a way to print the integer back out with decimal places (if needed) in a JLabel.

See above.

I suppose I can convert back to double

No, that totally defeats the purpose of using ints in the first place.

Pat Farrell
Rancher
Posts: 4678
7
• 2
Tyson Lindner wrote:Yeah I'm currently trying to figure this out. I can convert the double to int, but now I'm having trouble finding a way to print the integer back out with decimal places (if needed) in a JLabel. I suppose I can convert back to double and figure out how formatting works for JLabel which is something I was going to have to do anyway.

No, never double.

You want code like:

Tyson Lindner
Ranch Hand
Posts: 211
Pat Farrell wrote:
The standard approach is to use the Pattern and Matcher classes to process a regular expression. This also allows you to accept and ignore commas in the number. Sadly, its a bit complex to get the regex exactly right, you can get it close with a few minutes of effort, but getting it exact for all cases is a lot of effort.

Thanks, I guess I'll have to look into these although I wish there was an easier way.