All-
I have an app in which the users inputs data such as the cost of a dinner bill and the tip percentage and the number of people. The app than takes the numbers and outputs the total bill cost and the amount each person has to pay. I am almost there but when the user inputs numbers that don't work well I get outputs like $23.576 or $34.999999999. My question is how do I make the app round the two output answers to two decimal places ($55.349 goes to $55.35)?
Thanks in advance!
String roundTwoDecimals(double d) {
DecimalFormat formatter = new DecimalFormat("#.##");
return formatter.format(d);
}
You can use Math.round like so:
double data = 55.349; // Your data value of whatever
int decimalPlaces = 2;
double roundBase = Math.pow(10, decimalPlaces);
data = (double)(Math.round(data * roundBase)) / roundBase;
System.out.println(data); // Prints "55.35"
Keep in mind, however: you should NOT use double when it comes to financial applications. Since yours appears to be small-scale, you should be fine, however, BigDecimal is much easier to use for purposes like these.
How to use BigDecimal: clicky.
Related
This question already has answers here:
Why not use Double or Float to represent currency?
(16 answers)
Closed 3 years ago.
I'm trying to split a bill and need to calculate how much each person would owe if the bill was split in even amounts. I know one amount will be different than the rest to account for the lost cents.
Assume 3 people try to split a bill for 200. 200 / 3 is 66.6666666667. What I planned on doing was charging the 2 first people 66.67 and the last gets lucky with the 66.66 bill.
At the minute, I have this so far:
private String calculateAmountToPay(String noOfParticipants, String owed) {
double amountOwed = Double.parseDouble(owed);
int noOfMembers = Integer.parseInt(noOfParticipants);
DecimalFormat amountFormat = new DecimalFormat("#.##");
amountFormat.setRoundingMode(RoundingMode.CEILING);
return amountFormat.format((amountOwed/(double)noOfMembers) / 100);
}
But this always will return 66.67. Is there a way that I can get it to only round up if there is a number greater than 2 decimal places, if not, it stays at 66.66 for example?
Maybe I'm approaching this the wrong way. I know currency can be finicky to deal with.
Before even thinking about arithmetic, you need to know that double is not an appropriate data type for use with currency, because it’s imprecise. So, stop using a floating point type (eg double) as the data type for the quantity of dollars and start using a precise type (eg long) as the data type for the quantity of cents.
The steps then to do the calculation would be to immediately convert everything, with rounding, to cents:
double amountOwed = ...;
int noOfMembers = ...;
long centsOwed = Math.round(amountOwed * 100);
long portionCents = Math.round(amountOwed * 100 / noOfMembers);
long errorCents = portionCents * noOfMembers - centsOwed;
Here’s one way to deal with the error:
long lastPortionCents = portionCents - errorCents;
But it’s possible that the error is more than 1 cent, so a better solution would be to spread the error out evenly by subtracting (or adding if the error is negative) 1 cent from the first (or last, or randomly chosen) errorCents diners.
The rest of the solution is then about rending the above, which I leave to the reader.
As a side note, using cents is how banks transmit amounts (at least for EFTPOS anyway).
Regarding basic software design, I would create a separate method that accepts integer cents and people count as its parameters and returns an array of the "split" amounts. Doing this will not only make your code easier to read, but it will compartmentaise the arithmetic operation and thus enable lots of simple tests to more easily be written, so you can know you have all the edge cases that you can think of covered.
You can use BigDecimal with half rounding mode:
private String calculateAmountToPay(String noOfParticipants, String owed) {
double amountOwed = Double.parseDouble(owed);
int noOfMembers = Integer.parseInt(noOfParticipants);
BigDecimal amount= new BigDecimal((amountOwed / (double) noOfMembers) / 100);
return amount.setScale(2, RoundingMode.HALF_UP).toString();
}
You can just do all the computation with basic primitives converting everything to cents (2 decimals precision), and dividing the left over cents over a portion of the members, no need to overcomplicate it with extra sdks/math manipulations. The following is a working example solving this problem entirely, using these suggestions:
public class AmountDivider {
private int totalMembers, luckies, unluckies;
private double totalAmount, amountPerLucky, amountPerUnlucky;
public AmountDivider(int numMembers, double amountOwed) {
totalMembers = numMembers;
totalAmount = amountOwed;
double centsOwed = amountOwed * 100;
int centsPerMember = (int)(centsOwed / totalMembers);
int centsLeft = (int)centsOwed - centsPerMember * totalMembers;
luckies = totalMembers - centsLeft;
amountPerLucky = centsPerMember / 100.0;
unluckies = centsLeft;
amountPerUnlucky = (centsPerMember + 1) / 100.0;
}
public String toString() {
String luckiesStr = String.format("%d lucky persons will pay %.2f", luckies, amountPerLucky);
String unluckiesStr = String.format("%d unlucky persons will pay %.2f", unluckies, amountPerUnlucky);
return String.format("For amount %f divided among %d: \n%s\n%s\n",
totalAmount, totalMembers, luckiesStr, unluckiesStr);
}
public static void main(String[] args) {
System.out.println(new AmountDivider(3, 200));
System.out.println(new AmountDivider(17, 365.99));
}
}
Complete code on GitHub
Hope this helps.
In java , I have confusion about store and get double value.
Currently i am creating software where some accounting part included,i want to store calculated value same as they are calculated like 202.234234234212312 and while in display i want to display it as 202.23 in 2 digit after decimal point.
and in calculation i want to do calculation with 2,4 or 6 digit.
for that i have 2 option
Store value as it is calculated and in getter method of amount field, i can format it like.
private Double amount;
public Double getAmount() {
DecimalFormat df2 = new DecimalFormat(".##");
return Double.valueOf(df2.format(amount));
}
but problem with this method is , it will get formatted number at all time i get amount. i can't get actual stored amount.
i can use 2 separate field for get and set.
private Double amount;
private Double amountFormatted;
public Double getAmount() {
return amount;
}
public Double getAmountFormatted() {
DecimalFormat df2 = new DecimalFormat(".##");
return Double.valueOf(df2.format(amountFormatted));
}
so please provide better way to store and get decimal value, Thank you.
First of all, all calculations involving money should be done in BigDecimal, not double. A double cannot represent quantities like 0.1 exactly.
Secondly, your getAmountFormatted should not return a Double but a String if it is only intended for output purposes.
Use the same amount variable for both methods.
If I understood you correctly, you just want to get different format for same value, you can just have one variable and 2 get fields like this:
private Double amount;
public Double getAmount() {
return amount;
}
public Double getAmountFormatted() {
DecimalFormat df2 = new DecimalFormat(".##");
return Double.valueOf(df2.format(amount));
}
It's not an entity's job to provide formatted data for display: leave formatting to the code that is actually doing the displaying. More to the point, it's not your job as the programmer of the entity class to 1) anticipate every future need for a formatted value, and 2) constantly update the entity class to provide new formatted values that you didn't (nay, couldn't) anticipate.
So just have the getAmount method return the raw unadulterated data:
public class Entity {
private BigDecimal amount;
public BigDecimal getAmount(){
return amount;
}
//...
}
and eliminate getAmountFormatted from the entity. When you want to display the amount formatted to two decimal places, just obtain the raw amount with getAmount() and format it right on the spot:
Entity e = ...;
DecimalFormat df = new DecimalFormat(".##");
System.out.println("The amount is " + df.format(e.getAmount());
Here's a little story that illustrates why I think this is the way to go...
Suppose there's a second amount, otherAmount in your entity, that was included at the time the entity was created because someone thought it might be needed in the future. And suppose that, because the field had no planned use at the time, you didn't bother to create a getOtherAmountFormatted() method to provide a two-decimal-formatted version of otherAmount.
Now the future arrives. The otherAmount field is now being used, and you need to start displaying it with two decimal places along with the original amount. You know you're going to have to add the line
System.out.println("The other amount is " + ...
into the code that's displaying the amounts. Only question is, how do you finish that line. Do you add into your entity class a getOtherAmountFormatted() method and then write:
System.out.println("The other amount is " + e.getOtherAmountFormatted()); // NO!!
Or do you not touch the entity class at all and just write:
System.out.println("The other amount is " + df.format(e.getOtherAmount()); // Yes!!
The entity isn't the class that ultimately needs the formatted version of otherAmount, so it shouldn't have to change just to accommodate some entirely other bit of code that now happens to need a formatted version of otherAmount. Especially when that other bit of code can just get the unformatted amount, which the unmodified entity can already provide, and then do the needed formatting for itself.
Next scenario: in the further future, yet another requirement has come up to print those amount fields, but now with with three decimal places. Are you going to add yet more methods into the entity class to provide three-decimal versions of the amounts (in addition to the ones already providing two-decimal versions)? Or will you not touch the entity class at all and just write, at the point you need those three-decimal formatted values:
DecimalFormat df3 = new DecimalFormat(".###");
// ...
System.out.println("The amount in 3 decimals is " + df3.format(e.getAmount());
System.out.println("The other amount in 3 decimals is " + df3.format(e.getOtherAmount());
I got the following BigDecimal from a Money-Object: BigDecimal 49.99 and I need this as Integer 4999, so everything I ask for is getting rid of the separator.
I could get this BigDecimal as String and remove the separator and parse it to an Integer, but I do not think that this is pretty.
BigDecimal bigPrice = moneyPrice.getValue();
Integer price = bigPrice.intValue();
Using this only responses with 49.
You need the method:
movePointRight(int n)
javadoc link: http://docs.oracle.com/javase/6/docs/api/java/math/BigDecimal.html#movePointRight(int)
example:
BigDecimal bd = new BigDecimal("398.0275");
System.out.println(bd.movePointRight(bd.scale()));
outputs:
3980275
If you want to use the number, just bd=bd.movePointRight(bd.scale());
Try this code:
BigDecimal db = new BigDecimal("49.99");
// multiply with 10^scale ( in your case 2)
db = db.multiply(new BigDecimal(10).pow( db.scale()));
System.out.println(db.intValue());
If it's currency and always to 2 dp, you could multiple it by 100. However as Davio comments, your code should make it clear why you're doing it.
If you want to convert, for example a price in GB pounds sterling to GB pence (100 pence in a pound) then multiplying it by 100 is the right thing to do.
It's not necessary to do any math on the BigDecimal; you can just call myBigDecimal.unscaledValue() to get the underlying unscaled BigInteger directly.
For a project at school, I have to make a java program to retrieve data from a database.
This is my code:
import java.text.*;
import java.util.*;
public class Tijdstip
{
public Tijdstip()
{
}
public double testTijd(String tijdstip1)
{
// splitting the time
String[] tokens = tijdstip1.split("\\s+");
int hours = Integer.parseInt(tokens[0]);
int minutes = Integer.parseInt(tokens[1]);
//returning the time
double result = hours + ((double)minutes/100);
return result;
}
}
I fill in a time as string like: "7 10", meaning 7:10am and it must return a double like 7.10
But it returns 7.1, how do I make it so it will return 7.10 instead of 7.1?
You need to understand the difference between how a number is represented and how it is displayed. There is no numeric difference between 7.1 and 7.10; there is no way to make the number one instead of the other. You can display 7.1 as 7.10 using output formatting such as found in the Format class.
As a side issue: Storing this as a double would be a bad idea in a program of any size. There are many classes for representing time, and they all take into account the non-decimal nature of time divisions. Doubles don't do this.
Try this
new DecimalFormat("#.00").format(result);
The short answer is that you cannot do this if you must keep the result as a double. The double doesn't know anything about leading or trailing zeros. You can only do this when the result is formatted as a String. E.g., String.format("%.2f", 7.1) gives the string "7.10". You can easily do this formatting every time you display the number, but you cannot make the number itself remember the extra zero.
When you return double it will always truncate your last number if it is zero. so make it a string and return
If you need double value which has only two digits after dicimal, you can try following:
double d = 1.164444;
double r = Math.rint(d * 100)/100;
System.out.println(r);
I have a simple calculation that uses doubles but I'm getting an unexpected result and I can't understand why?
import java.util.Scanner;
public class VersatileSnitSoft {
/**
* #param args
*/
public static void main(String[] args) {
Scanner myScanner = new Scanner(System.in);
double amount;
System.out.print("What’s the price of a CD-ROM? ");
amount = myScanner.nextDouble();
amount = amount + 25.00;
System.out.print("We will bill $");
System.out.print(amount);
System.out.println(" to your credit card.");
}
}
If I enter 2.99 the result I get is..
We will bill $27.990000000000002 to your credit card.
You cannot represent decimal values precisely whilst operating on doubles (or floats).
Use BigDecimal instead.
Edit (2)
Example here:
BigDecimal amount = new BigDecimal("2.99");
amount = amount.add(new BigDecimal("25.00"));
System.out.println(amount.toString());
Ouput:
27.99
Doubles (floating-point values in general) cannot always represent exactly what we think of intuitively as a precise value. This is because of the way in which floats are stored, and can vary from machine to machine and language to language. When you try to store 2.99, the actual value that is stored may be very slightly different (e.g. 2.990000000000002). This question gives a decent, quick overview of why.
You should therefore (as it says through the link) never use floating-point primitives to represent currency. Either use BigDecimal, or keep track of two integers yourself (e.g. int dollars; and int cents;).
use DecimalFormat to display 2 digit after whole number
DecimalFormat f = new DecimalFormat("##.00");
String amt=f.format(amount);
System.out.print("We will bill $");
System.out.print(amt);
http://www.browxy.com/SubmittedCode/21519
I believe this question has been asked a million times. You can find a good and quick description of it here Why not use Double or Float to represent currency?
If you are just fooling around and you want it to print properly use
String prettyNumber = String.format("%.2f", doubleNumber);
Which is going to print 2 floating points. It will look correct, but it is only correct if precision (in the magnitude of 10^-16 or so) is not of interest to you.