print number with 2 digits but round with 6 digits of precision - java

For getting a String with exactly 2 digits after the "." I can do something like:
DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
df.applyPattern("0.00");
df.setRoundingMode(RoundingMode.HALF_UP);
String output = df.format(value);
When I have a number such as 828.054999999702d, it will format it to 828.05 what is so far correct, since the next digit says "4" and it will round that down to nothing.
But what if I need to preserve more digits precision, just don't want to show it?
What I quickly created is this working code:
double prettyValue = value;
prettyValue = Math.round(prettyValue * 1000000d) / 1000000d;
prettyValue = Math.round(prettyValue * 100000d) / 100000d;
prettyValue = Math.round(prettyValue * 10000d) / 10000d;
prettyValue = Math.round(prettyValue * 1000d) / 1000d;
prettyValue = Math.round(prettyValue * 100d) / 100d;
DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
df.applyPattern("0.00");
df.setRoundingMode(RoundingMode.HALF_UP);
String output = df.format(prettyValue);
This will round the 6th, 5th, 4th, 3th and then the second place, NumberFormat will not have to do anything but just print the 2 remaining digits, after that there will be zeroes.
But I think there should be already an out-of-the-box rounding that I just don't see. Trying to do the same with BigDecimals leads to exactly the same issue for me.
The result I want is to get 828.054999999702 rounded to 828.06.

I'm not sure I fully understand your question so let me recap:
You have some double value with potentially more than 6 significant fraction digits.
You want to round that value to 6 fraction digits and use the HALF_UP mode.
You want to display only the first 2 fraction digits (I don't understand why but I won't question it).
In that case I'd suggest you first use BigDecimal for the rounding since otherwise you could get precision errors:
double value = 1.23456789;
BigDecimal rounded = BigDecimal.valueOf( value ).setScale(6, RoundingMode.HALF_UP);
That should result in the value 1.234568.
Then use NumberFormat like you did but always round down:
DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
df.applyPattern("#.##");
df.setRoundingMode(RoundingMode.DOWN);
String output = df.format( rounded );
That should result in 1.23.
With your input value of 4.23499999999235 you'd then get 4.235000 (rounded to 6 digits) and 4.23.
Edit: I'm not aware of any rounding mode that rounds 4.23499999999235 to 4.24 but you should be able to achieve it by chaining multiple setScale() calls:
BigDecimal rounded = BigDecimal.valueOf( value );
for( int digit = 6; digit >= 2; digit--) {
rounded = rounded .setScale( digit, RoundingMode.HALF_UP );
}
That should apply rounding to fraction digit 6, then 5 etc. and finally round to 4.24. I'm still not sure that's the right way to round but you know your requirements better than me :)

Considering you are outputting this to a string, why not use
String output = String.format(java.util.Locale.US,"%.2f", doubleValue);
instead of all of the DecimalFormat stuff? This will leave doubleValue as the original value, keeping the precision.

Related

Round according to nearest decimal value - java

I have used this one
Math.round(input * 100.0) / 100.0;
but it didn't work with my requirement. I want to round into two decimal points according to nearest decimal value.
firstly I want to check fourth decimal value
if it is 5 or above I want to add 1 into 3rd decimal value
then want to check 3rd one
if it is 5 or above I want to add 1 into 2nd one
ex: if I have 22.3246
refer above example number. 4th decimal no is 6.
we can add 1 into 3rd decimal value.
result : 22.325
now 3rd decimal no is 5. we can add 1 into 2nd decimal value
result : 22.33
I want to get result 22.33
If you want to respect the 4th decimal digit, you can do it in this way:
double val = Math.round(22.3246 * 1000.0) / 1000.0;
double result = Math.round(val * 100.0) / 100.0;
System.out.println(result); // print: 22.33
You can use BigDecimal class to accomplish this task, in combination with a scale and RoundingMode.HALF_UP.
Sample code:
System.out.println(new BigDecimal("22.3246").divide(BigDecimal.ONE,3,RoundingMode.HALF_UP)
.divide(BigDecimal.ONE,2,RoundingMode.HALF_UP));
Output:
22.33
According to your requirement, the greatest number to be rounded down to 22.32 is 22.3244444444.... From 22.32444...4445 on, iteratively rounding digit per digit will lead to 22.33.
So, you can add a bias of 0.005 - 0.0044444444 (standard rounding threshold minus your threshold), being 5/9000 and then round to the next 1/100 the standard way:
double BIAS = 5.0 / 9000.0;
double result = Math.round((input + BIAS) * 100.0) / 100.0;

Keep up to 3 decimals without doing any rounding

I have a double that I want to keep only 3 decimal places but without applying any rounding at all.
E.g. 92.36699 should be 92.366
I tried the following:
DecimalFormat nf= new DecimalFormat("#0.000");
String number = nf.format(originalNumber);
But this results in 92.367
How can I do what I need?
This isn't "no rounding", it's DOWN rounding. Simply set the roundingMode.
DecimalFormat nf = new DecimalFormat("#0.000");
nf.setRoundingMode(RoundingMode.DOWN);
String number = nf.format(originalNumber);
Note the difference between FLOOR and DOWN - only relevant for negative numbers. FLOOR rounds towards negative infinity therefore -92.36699 would become "-92.367".

Conditional NumberFormatter?

Is there a way to make a NumberFormatter that does the following:
If the Double is a whole number like 5.0, display "5"
If the Double is a decimal like 5.6, display "5.6"
I know this is an old question but this should do exactly what you asked:
var myNumber:Double = 0.0 // set to 5.0 or 5.6 to see result
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 4
let x = formatter.string(from: NSNumber(value: myNumber)) ?? "$\(myNumber)"
print("x = \(x)")
double someNum = 5.6d;
DecimalFormat df = new DecimalFormat("#.#");
String num = df.format(someNum);
if (num.substring(num.length - 1).equals("0")) {
num = num.substring(0, num.length - 2);
}
System.out.println(num);
The DecimalFormat instance formats the double into a string. The code checks the tenth place of precision, i.e. the first digit to the right of the decimal place, and if it be zero, then it shows only whole numbers. Otherwise, it shows the full precision.

java rounding to two decimals

I have a number
double num = 1.234567;
and I'm trying to keep only two decimals
num = (int)((num * 100) + 0.5) / 100.0;
but the actual number I got is 1.230000000001. How can I get rid of the 0000000001 part?
Try DecimalFormat:
DecimalFormat twoDp= new DecimalFormat("#.##");
Double.valueOf(twoDp.format(num));
You can't, unless you switch to a decimal radix. Doubles and floats don't have decimal places, they have binary places, so you can't round or truncate them to specific numbers of decimal places except in the cases where the value representations are congruent, i.e. the negative powers of 2.
So you have to either use DecimalFormat if you are presenting the result, or BigDecimal if you want to keep computing with it.
Any solution that ends by turning the value back into floating point is incorrect.
String result = String.format("%.2f", num);
Try this .. this should solve it
Double num = //value
num = //arithmetic
String temp =num.toString().split("\\.")[0];
int precision=temp.length();
BigDecimal b =new BigDecimal(num,new MathContext(precision+2));
System.out.println(b.doubleValue());

Format a double to omit unnecessary ".0" and never round off [duplicate]

This question already has answers here:
How to nicely format floating numbers to string without unnecessary decimal 0's
(29 answers)
Closed 9 years ago.
I know how to format a double to keep only the available decimal places (DP), up to a certain number of DPs. This example keeps up to 4 DPs.
double d = 1.0;
DecimalFormat df = new DecimalFormat("#.####");
System.out.print(df.format(d)); // returns "1"
double d = 1.23;
DecimalFormat df = new DecimalFormat("#.####");
System.out.print(df.format(d)); // returns "1.23"
double d = 1.2345678;
DecimalFormat df = new DecimalFormat("#.####");
System.out.print(df.format(d)); // returns "1.2346", rounding off: bad!
Now I want whole numbers e.g. 1.0 to return "1" without the unnecessary .0, and the # format character does provide that functionality. But how do I make sure that the number never gets rounded off? Is there any other way other than an arbitrarily long chain of # such as "#.###########################################"?
Or should I just use the default conversion of double to string, and truncate the ".0" if it appears at the end:
String s = "" + d;
if(s.substring(s.length()-2).equals(".0")) {
s=s.substring(0, s.length()-2);
}
Both ways seems terribly clumsy.
I use the following
double d =
String s = (long) d == d ? "" + (long) d : "" + d;
if you need Double instead for double. (Personally I would avoid using the wrapper if you can)
Double d =
String s = d.longValue() == d ? "" + d.longValue() : "" + d;
By default the rounding mode is Up for DecimalFormat. You can set different rounding format as per your requiremnet using setRoundingMode() method
Sample Code to set Rounding mode
double d = 1.2345678;
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.DOWN);
System.out.print(df.format(d));//result 1.2345 because of rounding down
You could use Double.doubleToLongBits() and extract the exponent and mantissa. From api doc:
Bit 63 (the bit that is selected by the mask 0x8000000000000000L)
represents the sign of the floating-point number. Bits 62-52 (the bits
that are selected by the mask 0x7ff0000000000000L) represent the
exponent. Bits 51-0 (the bits that are selected by the mask
0x000fffffffffffffL) represent the significand (sometimes called the
mantissa) of the floating-point number.
The exponent can be used to determine the number of significant digits, but you will always have to round at some point as some binary doulbe values will be endless in decimal.
For a binary representation you could simply use the mantissa and put the decimal dot at the right position (padding with zeros if necessary.

Categories

Resources