implementing price of item using BigDecimal in java
In a web application ,I want to model an ItemForSale which has a price field.I read elsewhere that float or double should not be used for currency fields due to rounding errors and BigDecimal is the proper type for this purpose.I created these classes
class ItemForSale {
private String name;
private BigDecimal price;
...
}
class MyUtils{
...
public static BigDecimal parsePriceOfItem(String priceStr){
BigDecimal price;
BigDecimal zero = new BigDecimal(0);
try{
price = new BigDecimal(priceStr);
}catch(NumberFormatException nfe){
price = zero;
}
if(price.doubleValue() < zero.doubleValue()){
开发者_JAVA百科 price = zero;
}
return price;
}
}
Is this the right way to parse a price string(as entered by user)?I wanted to treat negative and invalid strings (say 'abcd') as 0.
If there is a better way ,please tell me
thanks
mark
Why would you want to treat invalid input as 0? Surely you'd want to tell the user that they've made a mistake, rather than treating it as if they'd typed in zero.
If you're parsing user input, you should probably be using DecimalFormat
instead of the BigDecimal
constructor - that way it will use the appropriate cultural information. (Use setParseBigDecimal
to make DecimalFormat
parse to BigDecimal
instead of double
.)
Then instead of converting the BigDecimal values to doubles, use:
if (price.compareTo(BigDecimal.ZERO) < 0)
I would suggest that you should indicate to the user three different states:
- Number can't be parsed
- Number was negative (or possibly invalid in some other way; do you have a maximum value, or a maximum number of digits)?
- Number was valid
How costly is your most expensive item? If it is less than $21,474,836.47 you can safely express the price as a number of cents held in a normal int
.
You are correct to avoid float
and double
. The usual solution is to use an int
, or a long
, to hold the number of cents and adjust output formatting accordingly. There is usually no need to get into the complexities, and speed issues, of BigDecimal
.
Here's my suggestion:
public static BigDecimal parsePriceOfItem(String priceStr) {
try {
BigDecimal price = new BigDecimal(priceStr);
return price.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : price;
} catch(NumberFormatException nfe) {
return BigDecimal.ZERO;
}
}
精彩评论