How to always round in two decimals - java

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);

Related

How to always keep 2 decimal places in Java

I want to round off any double to a String with 2 decimal places in Java.
I have tried using DecimalFormat but it doesn't give the expected results.
Any help would be appreciated.
Ex: I/P: 3402100.5323
I want to convert this to:
O/P: 34.02
I've tried using DecimalFormat("##,##,##0.00", new DecimalFormatSymbols(Locale.US))
but this results in 34,02,100.53 whereas I want it to output 34.02
PS: If the I/P is 34.02 I would expect it to remain same even after applying the formatting
In my opinion, this can be achieved in 2 steps:
Transform the number into your customised
round-off. (3402100.5323 to 34.021005323). Divide the input with power of 10 to make it round to 2 digits.
Then transformed number can be pretty-printed to truncate value after 2 decimals (34.021005323 to 34.02)
public static void main(String[] args) {
double input = 3402100.5323;
double output = input / getDivisor(input);
System.out.printf("%.2f%n", output);
}
private static double getDivisor(double input) {
int length = String.valueOf((long) input).length();
return Math.pow(10, length - 2) ;
}
Output: 34.02
String.format("%0.2f", 34.021005323)
See
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#format(java.lang.String,%20java.lang.Object...) and
https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax
Turning one number into something completely different is, naturally, not the job of decimalformat.
To get from a number representing 3402100.5323 to the string "34.02", first you'd have to get a number that is closer to "34.02". In other words, divide by 10000.0 first.
From there, String.format("%.2f") seems like an easy path: That renders any double to a string, but never using more than 2 digits after the decimal separator. If you want 3400000.123 to turn into "34.00" and not "34", you can make that String.format("%.02f") to force the zeroes.
public String renderWhateverThatIs(double in) {
return String.format("%.02f", in / 100000.0);
}
renderWhateverThatIs(3402100.5323);
> 34,02
Note that the machine locale will dictate if you see a dot or a comma as separator. You can force the issue by explicitly passing a locale to format.
I think what you're looking for is the java.math.BigDecimal class (https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html).
In your case, it would look like this:
BigDecimal rounded = BigDecimal.valueOf(yourDoubleValueHere).setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(rounded); // 34.02
It can replace doubles (with more complex syntax though) by basically storing numbers in their decimal form, which means you could make operations on it and keep having two decimal places and avoid rounding issues.
EDIT: after thinking about it, it's probably overkill since you only want to get a String with the rounded value, but I'll leave it there just in case.
I don’t believe you can achieve what you want (First 4 digits converted into a 2 digit double with 2 decimal places) in a single step. I’ll break down the steps for an approach that I would try:
Convert the input double to a string
double d = 3402100.5323;
String dStr1 = String.valueOf(d); // dStr1 will be “3402100.5323”
Next, remove the decimal from the string
String dStr2 = dStr1.replace(‘.’,’’); // dStr2 will be “34021005323”
Then, grab the first 4 digits you are interested in
String dStr3 = dStr2.substring(0,4); // dStr3 will be “3402”
Finally, insert a decimal point
String result = dStr3.substring(0,2) + “.” + dStr3.substring(2); // result will be “34.02”
You can use format for this try this out it work 100% for me.
String.format("%.2f", value)
Helpful link
https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax

java removing trailing decimal digits causing .0 become .99

I want to simply have a function that converts a double with as many decimal places into 4 decimal places without rounding.
I have this code that has been working fine but found a random instance where it turned .0 into .99
Here are some sample outputs
4.12897456 ->4.1289
4.5 ->4.5
4.5231->4.5231
5.53->5.53
5.52->5.199 (Wrong conversion, I want it to be 5.52)
private static double get4Donly(double val){
double converted = ((long)(val * 1e4)) / 1e4;
return converted
}
EDIT: This conversion is called thousands of times, so please suggest a method where I dont have to create a new string all the time.
You can use DecimalFormat
import java.text.DecimalFormat;
import java.math.RoundingMode;
import java.util.Arrays;
public class MyClass {
public static void main(String args[]) {
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.DOWN);
for (Number n : Arrays.asList(4.12897456, 4.5, 4.5231, 5.53, 5.52)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
}
}
RoundingMode.DOWN rounds towards zero, new DecimalFormat("#.####") creates a DecimalFormat instance that formats numbers to a maximum of 4 decimal places. Put those two together and the above code produces the following output, which I believe matches your expectations:
4.1289
4.5
4.5231
5.53
5.52
Doubles just don't work like you think they do.
They are stored in a binary form, not a decimal form. Just like '1 divided by 3' is not representable in a decimal double (0.3333333333 is not enough, it's infinite 3s, so not representable, so you get a rounding error), but '1 divided by 5' is representable just fine, there are numbers that are representable, and numbers that end up rounded when storing things in a double type, but crucially things that seem perfectly roundable in decimal may not be roundable in binary.
Given that they don't match up, your idea of 'eh, I will multiply by 4, turn it to a long, then convert back to a double, then divide by 1000' is not going to let those digits go through unmolested. This is not how you round things, as you're introducing additional loss in addition to the loss you already started out with due to using doubles.
You have 3 solutions available:
Just print it properly
A double cannot be considered to 'have 4 digits after the decimal separator' because a double isn't decimal.
Therefore, it doesn't even make sense to say: Please round this double to at most 4 fractional digits.
That is the crucial realisation. Once you understand that you'll be well along the way :)
What you CAN do is 'please take this double and print it by using no more than 4 digits after the decimal separator'.
String out = String.format("%.4f", 5.52);
or you can use System.printf(XXX) which is short for System.print(String.format(XXX)).
This is probably what you want
forget doubles entirely
For some domains its better to ditch doubles and switch to longs or ints. For example, if you're doing finances, it's better to store the atomic unit as per that currency in a long, and forego doubles instead. So, for dollars, store cents-in-a-long. For euros, the same. For bitcoin, store satoshis. Write custom rendering to render back in a form that is palatable for that currency:
long value = 450; // $4.50
String formatCurrency(long cents) {
return String.format("%s%s%d.%02d", cents < 0 ? "-" : " ", "$", Math.abs(cents) / 100, Math.abs(cents) % 100);
}
Use BigDecimal
This is generally more trouble than it is worth, but it stores every digit, decimally - it represent everything decimal notation can (and it also cannot represent anything else - 1 divided by 3 is impossible in BigDecimal).
I would recommend using the .substring() method by converting the double to a String. It is much easier to understand and achieve since you do not require the number to be rounded.
Moreover, it is the most simple out of all the other methods, such as using DecimalFormat
In that case, you could do it like so:
private static double get4Donly(double val){
String num = String.valueOf(val);
return Double.parseDouble(num.substring(0, 6));
}
However, if the length of the result is smaller than 6 characters, you can do:
private static double get4Donly(double val){
String num = String.valueOf(val);
if(num.length()>6) {
return Double.parseDouble(num.substring(0, 6));
}else {
return val;
}
}

Java Set double value with all decimal point and get only 2 digit after decimal point

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());

Formatting Numbers to Army Time (Big Java Ex. 4.15)

I just started learning Java last week and am currently stuck on my exercise. Basically the problem is you take two numbers in army time, and then output what the difference is For example
Please Enter First time : 0900
Please Enter second time: 1730
Result - > 8 hours and 30 minutes
The bonus of the problem is to make sure the program works if the first time is bigger than the second. First I'm trying to solve the first part and heres what I have so far
class TimeInterval{
private double timeOne;
private double timeTwo;
public TimeInterval(double timeOne, double timeTwo){
timeOne = this.timeOne;
timeTwo = this.timeTwo;
}
public double getMinutes(){
double minuteDiff = timeTwo - timeOne;
minuteDiff = minuteDiff%60.0;
return minuteDiff;
}
public double getHours(){
double hours = timeTwo - timeOne;
hours = hours - getMinutes();
hours = hours/60.0;
return hours;
}
}
public class DataSet{
public static void main(String [] args){
TimeInterval time = new TimeInterval(0900,1730);
}
}
Now heres whats trippy. I'd like to make my new object with timeOne as 0900, but I'm getting an error. It says "Integer too long", that seems pretty funny to me so I did some research. In the last section of my book in chapter 4 we talking about formatting stuff, like with System.out.printf, and like %d, %f
I looked on SO and I found a way where I can do something like
String.format("%05d", yournumber);
Here you can put 5 0's before your number. The thing is, I'm not really sure how to implement this into my code. I tried setting timeTwo = String.format... etc, but then since its a string I can't really do math on it. Also it won't let me convert it to a double after String.format. How should I do approach my issue?
Numeric literals that start with a zero are interpreted as octal numbers, base 8, which can only use digits 0-7.
Thus the numeric literal 0900 is an invalid octal number. Try:
TimeInterval time = new TimeInterval(900, 1730);
Tip: Avoid using double for you fields and parameters. Use int instead, which will not suffer the imprecision of double. int can handle any number/time you need.

Exponential values vs double ( big decimal conversion already used)

i am using following function to format the double value to x.xx , but after that the result value started to end up with exponential value ( i have already read the answers which are advising to use the DecimalFormat or to plain text () methods but every where the system is giving error to change the types ...return types i am lost a bit now
can some one please help me in following method tweaks so that the returning values can be displayed as normal number instead of 3.343E32
Please note that the following function FD is used many times in code so i want to change it here only so i dont have to apply the formatting each and every results / variable..
public double fd(double x) {
BigDecimal bd_tax = new BigDecimal(x);
BigDecimal formated = bd_tax.setScale(2, BigDecimal.ROUND_UP);
x = Double.valueOf(formated.doubleValue());
return x;
}
You say, "...to format the double value...", but there is no code in your example that formats anything. Your fd(x) function takes a double as its argument, and it returns a double. It doesn't do anything else.
If your numbers really are in the neighborhood of 3.343E32, Then they're going to have a lot of digits: 33 digits before the decimal point. Is that what you were expecting?
Suggest you look at String.format() if you are trying to turn the double value into human readable text. Something like this, perhaps:
public String fd(double x) {
return String.format("%.2f", x);
}

Categories

Resources