Rounding a Bill Total in Java
This question already has an answer here:
Seeing result.setText("Tip Amount : " + " $ " + Double.toString(tip_cal));
, I'm guessing you're getting a lot of nines in your output. Doubles can't store cents exactly, so the math will be off, but if you're not a financial institution and just dealing with < $10,000 transactions, do
result.setText(String.format("Tip Amount :$%.2f", tip_cal));
One more thing: decimalFormat.format(totalcost);
is at best a no op, at worst a thread safety issue. It doesn't change the totalcost, it returns a StringBuffer (that shows you just how old it is).
You really want to be using BigDecimal here, rather than Double. As @David mentioned, "Doubles can't store cents exactly". BigDecimal type can. BigDecimal gives you precise control over precision, and rounding.
It's a much slower data type than Doubles, but for financial applications, it is far, far better.
Granted, a simple tip calculator is not High Finance, but the basic tenet still applies. When operating on things such as dollar values, BigDecimal is a much better data type.
Two things jump out at me....
First Math.round
can round DOWN, so a value of 5.22 would be rounded down to 6
, instead of up to 7
Now you can use (int)totalcost + 1
which basically trims off the decimal elements or Math.ceil(totalcost)
depending on your needs.
The second is you don't seem to understand how formatter are using
decimalFormat.format(totalcost);
Won't do anything, numbers are free from formatting information. Instead, you use a formatter to return a representation of the value in the specified format...
With all that tucked under our belts, something like...
String tipFormat = decimalFormat.format((tip_cal)
DecimalFormat decimalFormat = new DecimalFormat("$0.00");
decimalFormat.setMinimumFractionDigits(2);
try {
double amount = Double.parseDouble("5.21");
double tip_per = Double.parseDouble("20");
double tip_cal = (amount * tip_per) / 100;
double totalcost = amount + tip_cal;
double rounded = (int)totalcost + 1;
double roundtotal = rounded - totalcost;
System.out.println("Tip Amount : " + decimalFormat.format((tip_cal)));
System.out.println("Total Cost: " + decimalFormat.format(totalcost));
System.out.println("Tip: " + decimalFormat.format(roundtotal) + " to round bill");
System.out.println("Bill Tally: " + decimalFormat.format(totalcost + roundtotal));
} catch (NumberFormatException e) {
e.printStackTrace();
}
Will output...
Tip Amount : $1.04
Total Cost: $6.25
Tip: $0.75 to round bill
Bill Tally: $7.00
Having said all that, double
and float
are not well suited for monetary calculations. You can use long
or BigDecimal
as alternatives, for example...
NumberFormat nf = NumberFormat.getCurrencyInstance();
try {
BigDecimal amount = new BigDecimal(Double.parseDouble("5.21"));
BigDecimal tip_per = new BigDecimal(Double.parseDouble("20"));
BigDecimal tip_cal = amount.multiply(tip_per).divide(new BigDecimal(100));
BigDecimal totalcost = amount.add(tip_cal);
BigDecimal rounded = totalcost.setScale(0, RoundingMode.CEILING);
BigDecimal roundtotal = rounded.subtract(totalcost);
System.out.println("Tip Amount : " + nf.format((tip_cal)));
System.out.println("Total Cost: " + nf.format(totalcost));
System.out.println("Tip: " + nf.format(roundtotal) + " to round bill");
System.out.println("Bill Tally: " + nf.format(totalcost.add(roundtotal)));
} catch (NumberFormatException e) {
e.printStackTrace();
}
This example uses the NumberFormat
class instead of creating it's own formatter based on the DecimalFormat
, not sure if this is available in Android or not, but you should consider using it (or the equivalent) as it takes into account the users local
上一篇: 在乘法中使用双精度(java)
下一篇: 以Java总计账单