Change double decimal spaces depending on int value - java

i want to change the decimal spaces of an double, depending on the int value that i use. I Figured out, that i can change the decimal spaces "manually" by changing to 10 or 1000 and so on, but i dont know how to accomplish this, other than changing said values in the code.
My second quest is how to round double values for example 19.657 up to 19.66, or 19.652 down to 19.65 .
Note :
WITHOUT the use of imports and only the default package
I use Java with Eclipse as my IDE
Thank you in advance for your effort :)
double x = 19.657821456;
int y = 3;
x = x*10;
x = (double)((int) x);
x = x /10;

You can use the DecimalFormat class to format your doubles.
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(formatter.format(10));
>10.00
This will also round values if they exceed the amount of decimals you specified
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(formatter.format(19.657));
>19.66

You can use Decimal Formate to format double value
Example:
private static final DecimalFormat df = new DecimalFormat("0.00");
public static void main(String[] args) {
double input = 3.14159265359;
System.out.println("double : " + input);
System.out.println("double : " + df.format(input)); //3.14
// DecimalFormat, default is RoundingMode.HALF_EVEN
df.setRoundingMode(RoundingMode.DOWN);
System.out.println("\ndouble (RoundingMode.DOWN) : " + df.format(input)); //3.14
df.setRoundingMode(RoundingMode.UP);
System.out.println("double (RoundingMode.UP) : " + df.format(input)); //3.15
}
Output :
double : 3.14159265359
double : 3.14
double (RoundingMode.DOWN) : 3.14
double (RoundingMode.UP) : 3.15

Variable number of digits after decimal. Basically same idea as code in question, just using Math methods, calculating the multiplier as needed (10 or 1000 in question):
public static double round(double value, int digits) {
if (digits < 0)
throw new IllegalArgumentException("digits must be non-negative: " + digits);
var mult = Math.pow(10, digits);
return Math.rint(value * mult) / mult;
}
If not allowed to use Math (standard lib, no import needed), we can calculate the multiplier in a loop and use an offset of 0.5 to round to the nearest integer (negative for negative numbers):
public static double round(double value, int digits) {
if (digits < 0)
throw new IllegalArgumentException("digits must be non-negative: " + digits);
var mult = 1.0;
for (var i = 0; i < digits; i++) {
mult *= 10;
}
var offset = value>0 ? 0.5 : -0.5;
return (int) (value * mult + offset) / mult;
}
Be warned that these methods will only work for small number of digits (intermediate results eventually exceeding the integer or even the double value range)
not tested - please test code before using

Related

I Don't know why my code won't print properly [duplicate]

What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the next number. This is the standard method of rounding most people expect in most situations.
I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.
I know one method of doing this is to use the String.format method:
String.format("%.5g%n", 0.912385);
returns:
0.91239
which is great, however it always displays numbers with 5 decimal places even if they are not significant:
String.format("%.5g%n", 0.912300);
returns:
0.91230
Another method is to use the DecimalFormatter:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returns:
0.91238
However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:
0.912385 -> 0.91239
0.912300 -> 0.9123
What is the best way to achieve this in Java?
Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
Example:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gives the output:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
Assuming value is a double, you can do:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method, or the toPlainString method for Java 5+ for a plain format string.
Sample program:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
As some others have noted, the correct answer is to use either DecimalFormat or BigDecimal. Floating-point doesn't have decimal places so you cannot possibly round/truncate to a specific number of them in the first place. You have to work in a decimal radix, and that is what those two classes do.
I am posting the following code as a counter-example to all the answers in this thread and indeed all over StackOverflow (and elsewhere) that recommend multiplication followed by truncation followed by division. It is incumbent on advocates of this technique to explain why the following code produces the wrong output in over 92% of cases.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Output of this program:
10001 trials 9251 errors
EDIT: To address some comments below I redid the modulus part of the test loop using BigDecimal and new MathContext(16) for the modulus operation as follows:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Result:
10001 trials 4401 errors
Suppose you have
double d = 9232.129394d;
you can use BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
or without BigDecimal
d = Math.round(d*100)/100.0d;
with both solutions d == 9232.13
You can use the DecimalFormat class.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
Real's Java How-to posts this solution, which is also compatible for versions before Java 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
UPDATE: BigDecimal.ROUND_HALF_UP is deprecated - Use RoundingMode
BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
#Milhous: the decimal format for rounding is excellent:
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
I would add that this method is very good at providing an actual
numeric, rounding mechanism - not only visually, but also when processing.
Hypothetical: you have to implement a rounding mechanism into a GUI
program. To alter the accuracy / precision of a result output simply
change the caret format (i.e. within the brackets). So that:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
would return as output: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
would return as output: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
would return as output: 0.9124
[EDIT: also if the caret format is like so ("#0.############") and you
enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat
does not produce any garbage (e.g. trailing zeroes) and will return:
3.1415926 .. if you're that way inclined. Granted, it's a little verbose
for the liking of some dev's - but hey, it's got a low memory footprint
during processing and is very easy to implement.]
So essentially, the beauty of DecimalFormat is that it simultaneously handles the string
appearance - as well as the level of rounding precision set. Ergo: you
get two benefits for the price of one code implementation. ;)
Here is a summary of what you can use if you want the result as String:
DecimalFormat#setRoundingMode():
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
BigDecimal#setScale()
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):
Precision from Apache Commons Math
double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
Functions from Colt
double rounded = Functions.round(0.00001).apply(0.912385)
Utils from Weka
double rounded = Utils.roundDouble(0.912385, 5)
You could use the following utility method-
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
A succinct solution:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) (Math.round(value * scale) / scale);
}
See also, https://stackoverflow.com/a/22186845/212950
Thanks to jpdymond for offering this.
Edit: Added round brackets. Casts the whole result to double, not the first argument only!
You can use BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
To achieve this we can use this formatter:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
or:
DecimalFormat df = new DecimalFormat("0.00"); :
Use this method to get always two decimals:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Defining this values:
91.32
5.22
11.5
1.2
2.6
Using the method we can get this results:
91.32
5.22
11.50
1.20
2.60
demo online.
If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.
Use BigDecimal or any other decimal-based format.
I do use BigDecimal for calculations, but bear in mind it is dependent on the size of
numbers you're dealing with. In most of my implementations, I find parsing from double or
integer to Long is sufficient enough for very large number calculations.
In fact, I've
recently used parsed-to-Long to get accurate representations (as opposed to hex results)
in a GUI for numbers as big as ################################# characters (as an
example).
Try this: org.apache.commons.math3.util.Precision.round(double x, int scale)
See: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html
The internal implemetation of this method is:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
Since I found no complete answer on this theme I've put together a class that should handle this properly, with support for:
Formatting: Easily format a double to string with a certain number of decimal places
Parsing: Parse the formatted value back to double
Locale: Format and parse using the default locale
Exponential notation: Start using exponential notation after a certain threshold
Usage is pretty simple:
(For the sake of this example I am using a custom locale)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Here is the class:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
Just in case someone still needs help with this. This solution works perfectly for me.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
returns a String with the desired output.
I agree with the chosen answer to use DecimalFormat --- or alternatively BigDecimal.
Please read Update below first!
However if you do want to round the double value and get a double value result, you can use org.apache.commons.math3.util.Precision.round(..) as mentioned above. The implementation uses BigDecimal, is slow and creates garbage.
A similar but fast and garbage-free method is provided by the DoubleRounder utility in the decimal4j library:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Will output
0.667
0.666
1000.0
9.00800700601E10
See
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Disclosure: I am involved in the decimal4j project.
Update:
As #iaforek pointed out DoubleRounder sometimes returns counterintuitive results. The reason is that it performs mathematically correct rounding. For instance DoubleRounder.round(256.025d, 2) will be rounded down to 256.02 because the double value represented as 256.025d is somewhat smaller than the rational value 256.025 and hence will be rounded down.
Notes:
This behaviour is very similar to that of the BigDecimal(double) constructor (but not to valueOf(double) which uses the string constructor).
The problem can be circumvented with a double rounding step to a higher precision first, but it is complicated and I am not going into the details here
For those reasons and everything mentioned above in this post I cannot recommend to use DoubleRounder.
So after reading most of the answers, I realized most of them won't be precise, in fact using BigDecimal seems like the best choice, but if you don't understand how the RoundingMode works, you will inevitable lose precision. I figured this out when working with big numbers in a project and thought it could help others having trouble rounding numbers. For example.
BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());
You would expect to get 1363.28 as an output, but you will end up with 1363.27, which is not expected, if you don't know what the RoundingMode is doing. So looking into the Oracle Docs, you will find the following description for RoundingMode.HALF_UP.
Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
So knowing this, we realized that we won't be getting an exact rounding, unless we want to round towards nearest neighbor. So, to accomplish an adequate round, we would need to loop from the n-1 decimal towards the desired decimals digits. For example.
private double round(double value, int places) throws IllegalArgumentException {
if (places < 0) throw new IllegalArgumentException();
// Cast the number to a String and then separate the decimals.
String stringValue = Double.toString(value);
String decimals = stringValue.split("\\.")[1];
// Round all the way to the desired number.
BigDecimal bd = new BigDecimal(stringValue);
for (int i = decimals.length()-1; i >= places; i--) {
bd = bd.setScale(i, RoundingMode.HALF_UP);
}
return bd.doubleValue();
}
This will end up giving us the expected output, which would be 1363.28.
I came here just wanting a simple answer on how to round a number. This is a supplemental answer to provide that.
How to round a number in Java
The most common case is to use Math.round().
Math.round(3.7) // 4
Numbers are rounded to the nearest whole number. A .5 value is rounded up. If you need different rounding behavior than that, you can use one of the other Math functions. See the comparison below.
round
As stated above, this rounds to the nearest whole number. .5 decimals round up. This method returns an int.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
ceil
Any decimal value is rounded up to the next integer. It goes to the ceiling. This method returns a double.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
floor
Any decimal value is rounded down to the next integer. This method returns a double.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
rint
This is similar to round in that decimal values round to the closest integer. However, unlike round, .5 values round to the even integer. This method returns a double.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
If you're using a technology that has a minimal JDK. Here's a way without any Java libs:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
here is my answer:
double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89
Here is a better function that rounds edge cases like 1.005 correctly.
Simply, we add the smallest possible float value (= 1 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
This is a little program to test it: ideone.com
/**
* Round half away from zero ('commercial' rounding)
* Uses correction to offset floating-point inaccuracies.
* Works symmetrically for positive and negative numbers.
*/
public static double round(double num, int digits) {
// epsilon correction
double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
double p = Math.pow(10, digits);
return Math.round(n * p) / p;
}
// test rounding of half
System.out.println(round(0.5, 0)); // 1
System.out.println(round(-0.5, 0)); // -1
// testing edge cases
System.out.println(round(1.005, 2)); // 1.01
System.out.println(round(2.175, 2)); // 2.18
System.out.println(round(5.015, 2)); // 5.02
System.out.println(round(-1.005, 2)); // -1.01
System.out.println(round(-2.175, 2)); // -2.18
System.out.println(round(-5.015, 2)); // -5.02
The code snippet below shows how to display n digits. The trick is to set variable pp to 1 followed by n zeros. In the example below, variable pp value has 5 zeros, so 5 digits will be displayed.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
If you're using DecimalFormat to convert double to String, it's very straightforward:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
There are several RoundingMode enum values to select from, depending upon the behaviour you require.
DecimalFormat is the best ways to output, but I don't prefer it. I always do this all the time, because it return the double value. So I can use it more than just output.
Math.round(selfEvaluate*100000d.0)/100000d.0;
OR
Math.round(selfEvaluate*100000d.0)*0.00000d1;
If you need large decimal places value, you can use BigDecimal instead. Anyways .0 is important. Without it the rounding of 0.33333d5 return 0.33333 and only 9 digits are allows. The second function without .0 has problems with 0.30000 return 0.30000000000000004.
I have used bellow like in java 8. it is working for me
double amount = 1000.431;
NumberFormat formatter = new DecimalFormat("##.00");
String output = formatter.format(amount);
System.out.println("output = " + output);
Output:
output = 1000.43
the following method could be used if need double
double getRandom(int decimalPoints) {
double a = Math.random();
int multiplier = (int) Math.pow(10, decimalPoints);
int b = (int) (a * multiplier);
return b / (double) multiplier;
}
for example getRandom(2)

sorting arrays and picking values from it [duplicate]

What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the next number. This is the standard method of rounding most people expect in most situations.
I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.
I know one method of doing this is to use the String.format method:
String.format("%.5g%n", 0.912385);
returns:
0.91239
which is great, however it always displays numbers with 5 decimal places even if they are not significant:
String.format("%.5g%n", 0.912300);
returns:
0.91230
Another method is to use the DecimalFormatter:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returns:
0.91238
However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:
0.912385 -> 0.91239
0.912300 -> 0.9123
What is the best way to achieve this in Java?
Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
Example:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gives the output:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
Assuming value is a double, you can do:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method, or the toPlainString method for Java 5+ for a plain format string.
Sample program:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
As some others have noted, the correct answer is to use either DecimalFormat or BigDecimal. Floating-point doesn't have decimal places so you cannot possibly round/truncate to a specific number of them in the first place. You have to work in a decimal radix, and that is what those two classes do.
I am posting the following code as a counter-example to all the answers in this thread and indeed all over StackOverflow (and elsewhere) that recommend multiplication followed by truncation followed by division. It is incumbent on advocates of this technique to explain why the following code produces the wrong output in over 92% of cases.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Output of this program:
10001 trials 9251 errors
EDIT: To address some comments below I redid the modulus part of the test loop using BigDecimal and new MathContext(16) for the modulus operation as follows:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Result:
10001 trials 4401 errors
Suppose you have
double d = 9232.129394d;
you can use BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
or without BigDecimal
d = Math.round(d*100)/100.0d;
with both solutions d == 9232.13
You can use the DecimalFormat class.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
Real's Java How-to posts this solution, which is also compatible for versions before Java 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
UPDATE: BigDecimal.ROUND_HALF_UP is deprecated - Use RoundingMode
BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
#Milhous: the decimal format for rounding is excellent:
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
I would add that this method is very good at providing an actual
numeric, rounding mechanism - not only visually, but also when processing.
Hypothetical: you have to implement a rounding mechanism into a GUI
program. To alter the accuracy / precision of a result output simply
change the caret format (i.e. within the brackets). So that:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
would return as output: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
would return as output: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
would return as output: 0.9124
[EDIT: also if the caret format is like so ("#0.############") and you
enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat
does not produce any garbage (e.g. trailing zeroes) and will return:
3.1415926 .. if you're that way inclined. Granted, it's a little verbose
for the liking of some dev's - but hey, it's got a low memory footprint
during processing and is very easy to implement.]
So essentially, the beauty of DecimalFormat is that it simultaneously handles the string
appearance - as well as the level of rounding precision set. Ergo: you
get two benefits for the price of one code implementation. ;)
Here is a summary of what you can use if you want the result as String:
DecimalFormat#setRoundingMode():
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
BigDecimal#setScale()
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):
Precision from Apache Commons Math
double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
Functions from Colt
double rounded = Functions.round(0.00001).apply(0.912385)
Utils from Weka
double rounded = Utils.roundDouble(0.912385, 5)
You could use the following utility method-
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
A succinct solution:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) (Math.round(value * scale) / scale);
}
See also, https://stackoverflow.com/a/22186845/212950
Thanks to jpdymond for offering this.
Edit: Added round brackets. Casts the whole result to double, not the first argument only!
You can use BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
To achieve this we can use this formatter:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
or:
DecimalFormat df = new DecimalFormat("0.00"); :
Use this method to get always two decimals:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Defining this values:
91.32
5.22
11.5
1.2
2.6
Using the method we can get this results:
91.32
5.22
11.50
1.20
2.60
demo online.
If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.
Use BigDecimal or any other decimal-based format.
I do use BigDecimal for calculations, but bear in mind it is dependent on the size of
numbers you're dealing with. In most of my implementations, I find parsing from double or
integer to Long is sufficient enough for very large number calculations.
In fact, I've
recently used parsed-to-Long to get accurate representations (as opposed to hex results)
in a GUI for numbers as big as ################################# characters (as an
example).
Try this: org.apache.commons.math3.util.Precision.round(double x, int scale)
See: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html
The internal implemetation of this method is:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
Since I found no complete answer on this theme I've put together a class that should handle this properly, with support for:
Formatting: Easily format a double to string with a certain number of decimal places
Parsing: Parse the formatted value back to double
Locale: Format and parse using the default locale
Exponential notation: Start using exponential notation after a certain threshold
Usage is pretty simple:
(For the sake of this example I am using a custom locale)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Here is the class:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
Just in case someone still needs help with this. This solution works perfectly for me.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
returns a String with the desired output.
I agree with the chosen answer to use DecimalFormat --- or alternatively BigDecimal.
Please read Update below first!
However if you do want to round the double value and get a double value result, you can use org.apache.commons.math3.util.Precision.round(..) as mentioned above. The implementation uses BigDecimal, is slow and creates garbage.
A similar but fast and garbage-free method is provided by the DoubleRounder utility in the decimal4j library:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Will output
0.667
0.666
1000.0
9.00800700601E10
See
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Disclosure: I am involved in the decimal4j project.
Update:
As #iaforek pointed out DoubleRounder sometimes returns counterintuitive results. The reason is that it performs mathematically correct rounding. For instance DoubleRounder.round(256.025d, 2) will be rounded down to 256.02 because the double value represented as 256.025d is somewhat smaller than the rational value 256.025 and hence will be rounded down.
Notes:
This behaviour is very similar to that of the BigDecimal(double) constructor (but not to valueOf(double) which uses the string constructor).
The problem can be circumvented with a double rounding step to a higher precision first, but it is complicated and I am not going into the details here
For those reasons and everything mentioned above in this post I cannot recommend to use DoubleRounder.
So after reading most of the answers, I realized most of them won't be precise, in fact using BigDecimal seems like the best choice, but if you don't understand how the RoundingMode works, you will inevitable lose precision. I figured this out when working with big numbers in a project and thought it could help others having trouble rounding numbers. For example.
BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());
You would expect to get 1363.28 as an output, but you will end up with 1363.27, which is not expected, if you don't know what the RoundingMode is doing. So looking into the Oracle Docs, you will find the following description for RoundingMode.HALF_UP.
Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
So knowing this, we realized that we won't be getting an exact rounding, unless we want to round towards nearest neighbor. So, to accomplish an adequate round, we would need to loop from the n-1 decimal towards the desired decimals digits. For example.
private double round(double value, int places) throws IllegalArgumentException {
if (places < 0) throw new IllegalArgumentException();
// Cast the number to a String and then separate the decimals.
String stringValue = Double.toString(value);
String decimals = stringValue.split("\\.")[1];
// Round all the way to the desired number.
BigDecimal bd = new BigDecimal(stringValue);
for (int i = decimals.length()-1; i >= places; i--) {
bd = bd.setScale(i, RoundingMode.HALF_UP);
}
return bd.doubleValue();
}
This will end up giving us the expected output, which would be 1363.28.
I came here just wanting a simple answer on how to round a number. This is a supplemental answer to provide that.
How to round a number in Java
The most common case is to use Math.round().
Math.round(3.7) // 4
Numbers are rounded to the nearest whole number. A .5 value is rounded up. If you need different rounding behavior than that, you can use one of the other Math functions. See the comparison below.
round
As stated above, this rounds to the nearest whole number. .5 decimals round up. This method returns an int.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
ceil
Any decimal value is rounded up to the next integer. It goes to the ceiling. This method returns a double.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
floor
Any decimal value is rounded down to the next integer. This method returns a double.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
rint
This is similar to round in that decimal values round to the closest integer. However, unlike round, .5 values round to the even integer. This method returns a double.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
If you're using a technology that has a minimal JDK. Here's a way without any Java libs:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
here is my answer:
double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89
Here is a better function that rounds edge cases like 1.005 correctly.
Simply, we add the smallest possible float value (= 1 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
This is a little program to test it: ideone.com
/**
* Round half away from zero ('commercial' rounding)
* Uses correction to offset floating-point inaccuracies.
* Works symmetrically for positive and negative numbers.
*/
public static double round(double num, int digits) {
// epsilon correction
double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
double p = Math.pow(10, digits);
return Math.round(n * p) / p;
}
// test rounding of half
System.out.println(round(0.5, 0)); // 1
System.out.println(round(-0.5, 0)); // -1
// testing edge cases
System.out.println(round(1.005, 2)); // 1.01
System.out.println(round(2.175, 2)); // 2.18
System.out.println(round(5.015, 2)); // 5.02
System.out.println(round(-1.005, 2)); // -1.01
System.out.println(round(-2.175, 2)); // -2.18
System.out.println(round(-5.015, 2)); // -5.02
The code snippet below shows how to display n digits. The trick is to set variable pp to 1 followed by n zeros. In the example below, variable pp value has 5 zeros, so 5 digits will be displayed.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
If you're using DecimalFormat to convert double to String, it's very straightforward:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
There are several RoundingMode enum values to select from, depending upon the behaviour you require.
DecimalFormat is the best ways to output, but I don't prefer it. I always do this all the time, because it return the double value. So I can use it more than just output.
Math.round(selfEvaluate*100000d.0)/100000d.0;
OR
Math.round(selfEvaluate*100000d.0)*0.00000d1;
If you need large decimal places value, you can use BigDecimal instead. Anyways .0 is important. Without it the rounding of 0.33333d5 return 0.33333 and only 9 digits are allows. The second function without .0 has problems with 0.30000 return 0.30000000000000004.
I have used bellow like in java 8. it is working for me
double amount = 1000.431;
NumberFormat formatter = new DecimalFormat("##.00");
String output = formatter.format(amount);
System.out.println("output = " + output);
Output:
output = 1000.43
the following method could be used if need double
double getRandom(int decimalPoints) {
double a = Math.random();
int multiplier = (int) Math.pow(10, decimalPoints);
int b = (int) (a * multiplier);
return b / (double) multiplier;
}
for example getRandom(2)

Add decimal places to string in java using String.format()? [duplicate]

What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the next number. This is the standard method of rounding most people expect in most situations.
I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.
I know one method of doing this is to use the String.format method:
String.format("%.5g%n", 0.912385);
returns:
0.91239
which is great, however it always displays numbers with 5 decimal places even if they are not significant:
String.format("%.5g%n", 0.912300);
returns:
0.91230
Another method is to use the DecimalFormatter:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returns:
0.91238
However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:
0.912385 -> 0.91239
0.912300 -> 0.9123
What is the best way to achieve this in Java?
Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
Example:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gives the output:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
Assuming value is a double, you can do:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method, or the toPlainString method for Java 5+ for a plain format string.
Sample program:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
As some others have noted, the correct answer is to use either DecimalFormat or BigDecimal. Floating-point doesn't have decimal places so you cannot possibly round/truncate to a specific number of them in the first place. You have to work in a decimal radix, and that is what those two classes do.
I am posting the following code as a counter-example to all the answers in this thread and indeed all over StackOverflow (and elsewhere) that recommend multiplication followed by truncation followed by division. It is incumbent on advocates of this technique to explain why the following code produces the wrong output in over 92% of cases.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Output of this program:
10001 trials 9251 errors
EDIT: To address some comments below I redid the modulus part of the test loop using BigDecimal and new MathContext(16) for the modulus operation as follows:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Result:
10001 trials 4401 errors
Suppose you have
double d = 9232.129394d;
you can use BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
or without BigDecimal
d = Math.round(d*100)/100.0d;
with both solutions d == 9232.13
You can use the DecimalFormat class.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
Real's Java How-to posts this solution, which is also compatible for versions before Java 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
UPDATE: BigDecimal.ROUND_HALF_UP is deprecated - Use RoundingMode
BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
#Milhous: the decimal format for rounding is excellent:
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
I would add that this method is very good at providing an actual
numeric, rounding mechanism - not only visually, but also when processing.
Hypothetical: you have to implement a rounding mechanism into a GUI
program. To alter the accuracy / precision of a result output simply
change the caret format (i.e. within the brackets). So that:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
would return as output: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
would return as output: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
would return as output: 0.9124
[EDIT: also if the caret format is like so ("#0.############") and you
enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat
does not produce any garbage (e.g. trailing zeroes) and will return:
3.1415926 .. if you're that way inclined. Granted, it's a little verbose
for the liking of some dev's - but hey, it's got a low memory footprint
during processing and is very easy to implement.]
So essentially, the beauty of DecimalFormat is that it simultaneously handles the string
appearance - as well as the level of rounding precision set. Ergo: you
get two benefits for the price of one code implementation. ;)
Here is a summary of what you can use if you want the result as String:
DecimalFormat#setRoundingMode():
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
BigDecimal#setScale()
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):
Precision from Apache Commons Math
double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
Functions from Colt
double rounded = Functions.round(0.00001).apply(0.912385)
Utils from Weka
double rounded = Utils.roundDouble(0.912385, 5)
You could use the following utility method-
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
A succinct solution:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) (Math.round(value * scale) / scale);
}
See also, https://stackoverflow.com/a/22186845/212950
Thanks to jpdymond for offering this.
Edit: Added round brackets. Casts the whole result to double, not the first argument only!
You can use BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
To achieve this we can use this formatter:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
or:
DecimalFormat df = new DecimalFormat("0.00"); :
Use this method to get always two decimals:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Defining this values:
91.32
5.22
11.5
1.2
2.6
Using the method we can get this results:
91.32
5.22
11.50
1.20
2.60
demo online.
If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.
Use BigDecimal or any other decimal-based format.
I do use BigDecimal for calculations, but bear in mind it is dependent on the size of
numbers you're dealing with. In most of my implementations, I find parsing from double or
integer to Long is sufficient enough for very large number calculations.
In fact, I've
recently used parsed-to-Long to get accurate representations (as opposed to hex results)
in a GUI for numbers as big as ################################# characters (as an
example).
Try this: org.apache.commons.math3.util.Precision.round(double x, int scale)
See: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html
The internal implemetation of this method is:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
Since I found no complete answer on this theme I've put together a class that should handle this properly, with support for:
Formatting: Easily format a double to string with a certain number of decimal places
Parsing: Parse the formatted value back to double
Locale: Format and parse using the default locale
Exponential notation: Start using exponential notation after a certain threshold
Usage is pretty simple:
(For the sake of this example I am using a custom locale)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Here is the class:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
Just in case someone still needs help with this. This solution works perfectly for me.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
returns a String with the desired output.
I agree with the chosen answer to use DecimalFormat --- or alternatively BigDecimal.
Please read Update below first!
However if you do want to round the double value and get a double value result, you can use org.apache.commons.math3.util.Precision.round(..) as mentioned above. The implementation uses BigDecimal, is slow and creates garbage.
A similar but fast and garbage-free method is provided by the DoubleRounder utility in the decimal4j library:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Will output
0.667
0.666
1000.0
9.00800700601E10
See
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Disclosure: I am involved in the decimal4j project.
Update:
As #iaforek pointed out DoubleRounder sometimes returns counterintuitive results. The reason is that it performs mathematically correct rounding. For instance DoubleRounder.round(256.025d, 2) will be rounded down to 256.02 because the double value represented as 256.025d is somewhat smaller than the rational value 256.025 and hence will be rounded down.
Notes:
This behaviour is very similar to that of the BigDecimal(double) constructor (but not to valueOf(double) which uses the string constructor).
The problem can be circumvented with a double rounding step to a higher precision first, but it is complicated and I am not going into the details here
For those reasons and everything mentioned above in this post I cannot recommend to use DoubleRounder.
So after reading most of the answers, I realized most of them won't be precise, in fact using BigDecimal seems like the best choice, but if you don't understand how the RoundingMode works, you will inevitable lose precision. I figured this out when working with big numbers in a project and thought it could help others having trouble rounding numbers. For example.
BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());
You would expect to get 1363.28 as an output, but you will end up with 1363.27, which is not expected, if you don't know what the RoundingMode is doing. So looking into the Oracle Docs, you will find the following description for RoundingMode.HALF_UP.
Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
So knowing this, we realized that we won't be getting an exact rounding, unless we want to round towards nearest neighbor. So, to accomplish an adequate round, we would need to loop from the n-1 decimal towards the desired decimals digits. For example.
private double round(double value, int places) throws IllegalArgumentException {
if (places < 0) throw new IllegalArgumentException();
// Cast the number to a String and then separate the decimals.
String stringValue = Double.toString(value);
String decimals = stringValue.split("\\.")[1];
// Round all the way to the desired number.
BigDecimal bd = new BigDecimal(stringValue);
for (int i = decimals.length()-1; i >= places; i--) {
bd = bd.setScale(i, RoundingMode.HALF_UP);
}
return bd.doubleValue();
}
This will end up giving us the expected output, which would be 1363.28.
I came here just wanting a simple answer on how to round a number. This is a supplemental answer to provide that.
How to round a number in Java
The most common case is to use Math.round().
Math.round(3.7) // 4
Numbers are rounded to the nearest whole number. A .5 value is rounded up. If you need different rounding behavior than that, you can use one of the other Math functions. See the comparison below.
round
As stated above, this rounds to the nearest whole number. .5 decimals round up. This method returns an int.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
ceil
Any decimal value is rounded up to the next integer. It goes to the ceiling. This method returns a double.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
floor
Any decimal value is rounded down to the next integer. This method returns a double.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
rint
This is similar to round in that decimal values round to the closest integer. However, unlike round, .5 values round to the even integer. This method returns a double.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
If you're using a technology that has a minimal JDK. Here's a way without any Java libs:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
here is my answer:
double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89
Here is a better function that rounds edge cases like 1.005 correctly.
Simply, we add the smallest possible float value (= 1 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
This is a little program to test it: ideone.com
/**
* Round half away from zero ('commercial' rounding)
* Uses correction to offset floating-point inaccuracies.
* Works symmetrically for positive and negative numbers.
*/
public static double round(double num, int digits) {
// epsilon correction
double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
double p = Math.pow(10, digits);
return Math.round(n * p) / p;
}
// test rounding of half
System.out.println(round(0.5, 0)); // 1
System.out.println(round(-0.5, 0)); // -1
// testing edge cases
System.out.println(round(1.005, 2)); // 1.01
System.out.println(round(2.175, 2)); // 2.18
System.out.println(round(5.015, 2)); // 5.02
System.out.println(round(-1.005, 2)); // -1.01
System.out.println(round(-2.175, 2)); // -2.18
System.out.println(round(-5.015, 2)); // -5.02
The code snippet below shows how to display n digits. The trick is to set variable pp to 1 followed by n zeros. In the example below, variable pp value has 5 zeros, so 5 digits will be displayed.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
If you're using DecimalFormat to convert double to String, it's very straightforward:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
There are several RoundingMode enum values to select from, depending upon the behaviour you require.
DecimalFormat is the best ways to output, but I don't prefer it. I always do this all the time, because it return the double value. So I can use it more than just output.
Math.round(selfEvaluate*100000d.0)/100000d.0;
OR
Math.round(selfEvaluate*100000d.0)*0.00000d1;
If you need large decimal places value, you can use BigDecimal instead. Anyways .0 is important. Without it the rounding of 0.33333d5 return 0.33333 and only 9 digits are allows. The second function without .0 has problems with 0.30000 return 0.30000000000000004.
I have used bellow like in java 8. it is working for me
double amount = 1000.431;
NumberFormat formatter = new DecimalFormat("##.00");
String output = formatter.format(amount);
System.out.println("output = " + output);
Output:
output = 1000.43
the following method could be used if need double
double getRandom(int decimalPoints) {
double a = Math.random();
int multiplier = (int) Math.pow(10, decimalPoints);
int b = (int) (a * multiplier);
return b / (double) multiplier;
}
for example getRandom(2)

Recurring decimal rounding to second place [duplicate]

What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the next number. This is the standard method of rounding most people expect in most situations.
I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.
I know one method of doing this is to use the String.format method:
String.format("%.5g%n", 0.912385);
returns:
0.91239
which is great, however it always displays numbers with 5 decimal places even if they are not significant:
String.format("%.5g%n", 0.912300);
returns:
0.91230
Another method is to use the DecimalFormatter:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returns:
0.91238
However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:
0.912385 -> 0.91239
0.912300 -> 0.9123
What is the best way to achieve this in Java?
Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
Example:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gives the output:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
Assuming value is a double, you can do:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method, or the toPlainString method for Java 5+ for a plain format string.
Sample program:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
As some others have noted, the correct answer is to use either DecimalFormat or BigDecimal. Floating-point doesn't have decimal places so you cannot possibly round/truncate to a specific number of them in the first place. You have to work in a decimal radix, and that is what those two classes do.
I am posting the following code as a counter-example to all the answers in this thread and indeed all over StackOverflow (and elsewhere) that recommend multiplication followed by truncation followed by division. It is incumbent on advocates of this technique to explain why the following code produces the wrong output in over 92% of cases.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Output of this program:
10001 trials 9251 errors
EDIT: To address some comments below I redid the modulus part of the test loop using BigDecimal and new MathContext(16) for the modulus operation as follows:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Result:
10001 trials 4401 errors
Suppose you have
double d = 9232.129394d;
you can use BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
or without BigDecimal
d = Math.round(d*100)/100.0d;
with both solutions d == 9232.13
You can use the DecimalFormat class.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
Real's Java How-to posts this solution, which is also compatible for versions before Java 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
UPDATE: BigDecimal.ROUND_HALF_UP is deprecated - Use RoundingMode
BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
#Milhous: the decimal format for rounding is excellent:
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
I would add that this method is very good at providing an actual
numeric, rounding mechanism - not only visually, but also when processing.
Hypothetical: you have to implement a rounding mechanism into a GUI
program. To alter the accuracy / precision of a result output simply
change the caret format (i.e. within the brackets). So that:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
would return as output: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
would return as output: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
would return as output: 0.9124
[EDIT: also if the caret format is like so ("#0.############") and you
enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat
does not produce any garbage (e.g. trailing zeroes) and will return:
3.1415926 .. if you're that way inclined. Granted, it's a little verbose
for the liking of some dev's - but hey, it's got a low memory footprint
during processing and is very easy to implement.]
So essentially, the beauty of DecimalFormat is that it simultaneously handles the string
appearance - as well as the level of rounding precision set. Ergo: you
get two benefits for the price of one code implementation. ;)
Here is a summary of what you can use if you want the result as String:
DecimalFormat#setRoundingMode():
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
BigDecimal#setScale()
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):
Precision from Apache Commons Math
double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
Functions from Colt
double rounded = Functions.round(0.00001).apply(0.912385)
Utils from Weka
double rounded = Utils.roundDouble(0.912385, 5)
You could use the following utility method-
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
A succinct solution:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) (Math.round(value * scale) / scale);
}
See also, https://stackoverflow.com/a/22186845/212950
Thanks to jpdymond for offering this.
Edit: Added round brackets. Casts the whole result to double, not the first argument only!
You can use BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
To achieve this we can use this formatter:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
or:
DecimalFormat df = new DecimalFormat("0.00"); :
Use this method to get always two decimals:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Defining this values:
91.32
5.22
11.5
1.2
2.6
Using the method we can get this results:
91.32
5.22
11.50
1.20
2.60
demo online.
If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.
Use BigDecimal or any other decimal-based format.
I do use BigDecimal for calculations, but bear in mind it is dependent on the size of
numbers you're dealing with. In most of my implementations, I find parsing from double or
integer to Long is sufficient enough for very large number calculations.
In fact, I've
recently used parsed-to-Long to get accurate representations (as opposed to hex results)
in a GUI for numbers as big as ################################# characters (as an
example).
Try this: org.apache.commons.math3.util.Precision.round(double x, int scale)
See: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html
The internal implemetation of this method is:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
Since I found no complete answer on this theme I've put together a class that should handle this properly, with support for:
Formatting: Easily format a double to string with a certain number of decimal places
Parsing: Parse the formatted value back to double
Locale: Format and parse using the default locale
Exponential notation: Start using exponential notation after a certain threshold
Usage is pretty simple:
(For the sake of this example I am using a custom locale)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Here is the class:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
Just in case someone still needs help with this. This solution works perfectly for me.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
returns a String with the desired output.
I agree with the chosen answer to use DecimalFormat --- or alternatively BigDecimal.
Please read Update below first!
However if you do want to round the double value and get a double value result, you can use org.apache.commons.math3.util.Precision.round(..) as mentioned above. The implementation uses BigDecimal, is slow and creates garbage.
A similar but fast and garbage-free method is provided by the DoubleRounder utility in the decimal4j library:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Will output
0.667
0.666
1000.0
9.00800700601E10
See
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Disclosure: I am involved in the decimal4j project.
Update:
As #iaforek pointed out DoubleRounder sometimes returns counterintuitive results. The reason is that it performs mathematically correct rounding. For instance DoubleRounder.round(256.025d, 2) will be rounded down to 256.02 because the double value represented as 256.025d is somewhat smaller than the rational value 256.025 and hence will be rounded down.
Notes:
This behaviour is very similar to that of the BigDecimal(double) constructor (but not to valueOf(double) which uses the string constructor).
The problem can be circumvented with a double rounding step to a higher precision first, but it is complicated and I am not going into the details here
For those reasons and everything mentioned above in this post I cannot recommend to use DoubleRounder.
So after reading most of the answers, I realized most of them won't be precise, in fact using BigDecimal seems like the best choice, but if you don't understand how the RoundingMode works, you will inevitable lose precision. I figured this out when working with big numbers in a project and thought it could help others having trouble rounding numbers. For example.
BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());
You would expect to get 1363.28 as an output, but you will end up with 1363.27, which is not expected, if you don't know what the RoundingMode is doing. So looking into the Oracle Docs, you will find the following description for RoundingMode.HALF_UP.
Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
So knowing this, we realized that we won't be getting an exact rounding, unless we want to round towards nearest neighbor. So, to accomplish an adequate round, we would need to loop from the n-1 decimal towards the desired decimals digits. For example.
private double round(double value, int places) throws IllegalArgumentException {
if (places < 0) throw new IllegalArgumentException();
// Cast the number to a String and then separate the decimals.
String stringValue = Double.toString(value);
String decimals = stringValue.split("\\.")[1];
// Round all the way to the desired number.
BigDecimal bd = new BigDecimal(stringValue);
for (int i = decimals.length()-1; i >= places; i--) {
bd = bd.setScale(i, RoundingMode.HALF_UP);
}
return bd.doubleValue();
}
This will end up giving us the expected output, which would be 1363.28.
I came here just wanting a simple answer on how to round a number. This is a supplemental answer to provide that.
How to round a number in Java
The most common case is to use Math.round().
Math.round(3.7) // 4
Numbers are rounded to the nearest whole number. A .5 value is rounded up. If you need different rounding behavior than that, you can use one of the other Math functions. See the comparison below.
round
As stated above, this rounds to the nearest whole number. .5 decimals round up. This method returns an int.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
ceil
Any decimal value is rounded up to the next integer. It goes to the ceiling. This method returns a double.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
floor
Any decimal value is rounded down to the next integer. This method returns a double.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
rint
This is similar to round in that decimal values round to the closest integer. However, unlike round, .5 values round to the even integer. This method returns a double.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
If you're using a technology that has a minimal JDK. Here's a way without any Java libs:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
here is my answer:
double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89
Here is a better function that rounds edge cases like 1.005 correctly.
Simply, we add the smallest possible float value (= 1 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
This is a little program to test it: ideone.com
/**
* Round half away from zero ('commercial' rounding)
* Uses correction to offset floating-point inaccuracies.
* Works symmetrically for positive and negative numbers.
*/
public static double round(double num, int digits) {
// epsilon correction
double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
double p = Math.pow(10, digits);
return Math.round(n * p) / p;
}
// test rounding of half
System.out.println(round(0.5, 0)); // 1
System.out.println(round(-0.5, 0)); // -1
// testing edge cases
System.out.println(round(1.005, 2)); // 1.01
System.out.println(round(2.175, 2)); // 2.18
System.out.println(round(5.015, 2)); // 5.02
System.out.println(round(-1.005, 2)); // -1.01
System.out.println(round(-2.175, 2)); // -2.18
System.out.println(round(-5.015, 2)); // -5.02
The code snippet below shows how to display n digits. The trick is to set variable pp to 1 followed by n zeros. In the example below, variable pp value has 5 zeros, so 5 digits will be displayed.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
If you're using DecimalFormat to convert double to String, it's very straightforward:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
There are several RoundingMode enum values to select from, depending upon the behaviour you require.
DecimalFormat is the best ways to output, but I don't prefer it. I always do this all the time, because it return the double value. So I can use it more than just output.
Math.round(selfEvaluate*100000d.0)/100000d.0;
OR
Math.round(selfEvaluate*100000d.0)*0.00000d1;
If you need large decimal places value, you can use BigDecimal instead. Anyways .0 is important. Without it the rounding of 0.33333d5 return 0.33333 and only 9 digits are allows. The second function without .0 has problems with 0.30000 return 0.30000000000000004.
I have used bellow like in java 8. it is working for me
double amount = 1000.431;
NumberFormat formatter = new DecimalFormat("##.00");
String output = formatter.format(amount);
System.out.println("output = " + output);
Output:
output = 1000.43
the following method could be used if need double
double getRandom(int decimalPoints) {
double a = Math.random();
int multiplier = (int) Math.pow(10, decimalPoints);
int b = (int) (a * multiplier);
return b / (double) multiplier;
}
for example getRandom(2)

How to round a number to n decimal places in Java

What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the next number. This is the standard method of rounding most people expect in most situations.
I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.
I know one method of doing this is to use the String.format method:
String.format("%.5g%n", 0.912385);
returns:
0.91239
which is great, however it always displays numbers with 5 decimal places even if they are not significant:
String.format("%.5g%n", 0.912300);
returns:
0.91230
Another method is to use the DecimalFormatter:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returns:
0.91238
However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:
0.912385 -> 0.91239
0.912300 -> 0.9123
What is the best way to achieve this in Java?
Use setRoundingMode, set the RoundingMode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
Example:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
gives the output:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
Assuming value is a double, you can do:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method, or the toPlainString method for Java 5+ for a plain format string.
Sample program:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
As some others have noted, the correct answer is to use either DecimalFormat or BigDecimal. Floating-point doesn't have decimal places so you cannot possibly round/truncate to a specific number of them in the first place. You have to work in a decimal radix, and that is what those two classes do.
I am posting the following code as a counter-example to all the answers in this thread and indeed all over StackOverflow (and elsewhere) that recommend multiplication followed by truncation followed by division. It is incumbent on advocates of this technique to explain why the following code produces the wrong output in over 92% of cases.
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
Output of this program:
10001 trials 9251 errors
EDIT: To address some comments below I redid the modulus part of the test loop using BigDecimal and new MathContext(16) for the modulus operation as follows:
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
Result:
10001 trials 4401 errors
Suppose you have
double d = 9232.129394d;
you can use BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
or without BigDecimal
d = Math.round(d*100)/100.0d;
with both solutions d == 9232.13
You can use the DecimalFormat class.
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
Real's Java How-to posts this solution, which is also compatible for versions before Java 1.6.
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
UPDATE: BigDecimal.ROUND_HALF_UP is deprecated - Use RoundingMode
BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
#Milhous: the decimal format for rounding is excellent:
You can also use the
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
I would add that this method is very good at providing an actual
numeric, rounding mechanism - not only visually, but also when processing.
Hypothetical: you have to implement a rounding mechanism into a GUI
program. To alter the accuracy / precision of a result output simply
change the caret format (i.e. within the brackets). So that:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
would return as output: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
would return as output: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
would return as output: 0.9124
[EDIT: also if the caret format is like so ("#0.############") and you
enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat
does not produce any garbage (e.g. trailing zeroes) and will return:
3.1415926 .. if you're that way inclined. Granted, it's a little verbose
for the liking of some dev's - but hey, it's got a low memory footprint
during processing and is very easy to implement.]
So essentially, the beauty of DecimalFormat is that it simultaneously handles the string
appearance - as well as the level of rounding precision set. Ergo: you
get two benefits for the price of one code implementation. ;)
Here is a summary of what you can use if you want the result as String:
DecimalFormat#setRoundingMode():
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
BigDecimal#setScale()
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):
Precision from Apache Commons Math
double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
Functions from Colt
double rounded = Functions.round(0.00001).apply(0.912385)
Utils from Weka
double rounded = Utils.roundDouble(0.912385, 5)
You could use the following utility method-
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
A succinct solution:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) (Math.round(value * scale) / scale);
}
See also, https://stackoverflow.com/a/22186845/212950
Thanks to jpdymond for offering this.
Edit: Added round brackets. Casts the whole result to double, not the first argument only!
You can use BigDecimal
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
Refer: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
To achieve this we can use this formatter:
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
or:
DecimalFormat df = new DecimalFormat("0.00"); :
Use this method to get always two decimals:
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
Defining this values:
91.32
5.22
11.5
1.2
2.6
Using the method we can get this results:
91.32
5.22
11.50
1.20
2.60
demo online.
If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.
Use BigDecimal or any other decimal-based format.
I do use BigDecimal for calculations, but bear in mind it is dependent on the size of
numbers you're dealing with. In most of my implementations, I find parsing from double or
integer to Long is sufficient enough for very large number calculations.
In fact, I've
recently used parsed-to-Long to get accurate representations (as opposed to hex results)
in a GUI for numbers as big as ################################# characters (as an
example).
Try this: org.apache.commons.math3.util.Precision.round(double x, int scale)
See: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Mathematics Library homepage is: http://commons.apache.org/proper/commons-math/index.html
The internal implemetation of this method is:
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
Since I found no complete answer on this theme I've put together a class that should handle this properly, with support for:
Formatting: Easily format a double to string with a certain number of decimal places
Parsing: Parse the formatted value back to double
Locale: Format and parse using the default locale
Exponential notation: Start using exponential notation after a certain threshold
Usage is pretty simple:
(For the sake of this example I am using a custom locale)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
Here is the class:
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
Just in case someone still needs help with this. This solution works perfectly for me.
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
returns a String with the desired output.
I agree with the chosen answer to use DecimalFormat --- or alternatively BigDecimal.
Please read Update below first!
However if you do want to round the double value and get a double value result, you can use org.apache.commons.math3.util.Precision.round(..) as mentioned above. The implementation uses BigDecimal, is slow and creates garbage.
A similar but fast and garbage-free method is provided by the DoubleRounder utility in the decimal4j library:
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
Will output
0.667
0.666
1000.0
9.00800700601E10
See
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Disclosure: I am involved in the decimal4j project.
Update:
As #iaforek pointed out DoubleRounder sometimes returns counterintuitive results. The reason is that it performs mathematically correct rounding. For instance DoubleRounder.round(256.025d, 2) will be rounded down to 256.02 because the double value represented as 256.025d is somewhat smaller than the rational value 256.025 and hence will be rounded down.
Notes:
This behaviour is very similar to that of the BigDecimal(double) constructor (but not to valueOf(double) which uses the string constructor).
The problem can be circumvented with a double rounding step to a higher precision first, but it is complicated and I am not going into the details here
For those reasons and everything mentioned above in this post I cannot recommend to use DoubleRounder.
So after reading most of the answers, I realized most of them won't be precise, in fact using BigDecimal seems like the best choice, but if you don't understand how the RoundingMode works, you will inevitable lose precision. I figured this out when working with big numbers in a project and thought it could help others having trouble rounding numbers. For example.
BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());
You would expect to get 1363.28 as an output, but you will end up with 1363.27, which is not expected, if you don't know what the RoundingMode is doing. So looking into the Oracle Docs, you will find the following description for RoundingMode.HALF_UP.
Rounding mode to round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
So knowing this, we realized that we won't be getting an exact rounding, unless we want to round towards nearest neighbor. So, to accomplish an adequate round, we would need to loop from the n-1 decimal towards the desired decimals digits. For example.
private double round(double value, int places) throws IllegalArgumentException {
if (places < 0) throw new IllegalArgumentException();
// Cast the number to a String and then separate the decimals.
String stringValue = Double.toString(value);
String decimals = stringValue.split("\\.")[1];
// Round all the way to the desired number.
BigDecimal bd = new BigDecimal(stringValue);
for (int i = decimals.length()-1; i >= places; i--) {
bd = bd.setScale(i, RoundingMode.HALF_UP);
}
return bd.doubleValue();
}
This will end up giving us the expected output, which would be 1363.28.
I came here just wanting a simple answer on how to round a number. This is a supplemental answer to provide that.
How to round a number in Java
The most common case is to use Math.round().
Math.round(3.7) // 4
Numbers are rounded to the nearest whole number. A .5 value is rounded up. If you need different rounding behavior than that, you can use one of the other Math functions. See the comparison below.
round
As stated above, this rounds to the nearest whole number. .5 decimals round up. This method returns an int.
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
ceil
Any decimal value is rounded up to the next integer. It goes to the ceiling. This method returns a double.
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
floor
Any decimal value is rounded down to the next integer. This method returns a double.
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
rint
This is similar to round in that decimal values round to the closest integer. However, unlike round, .5 values round to the even integer. This method returns a double.
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
If you're using a technology that has a minimal JDK. Here's a way without any Java libs:
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
here is my answer:
double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89
Here is a better function that rounds edge cases like 1.005 correctly.
Simply, we add the smallest possible float value (= 1 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
This is a little program to test it: ideone.com
/**
* Round half away from zero ('commercial' rounding)
* Uses correction to offset floating-point inaccuracies.
* Works symmetrically for positive and negative numbers.
*/
public static double round(double num, int digits) {
// epsilon correction
double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
double p = Math.pow(10, digits);
return Math.round(n * p) / p;
}
// test rounding of half
System.out.println(round(0.5, 0)); // 1
System.out.println(round(-0.5, 0)); // -1
// testing edge cases
System.out.println(round(1.005, 2)); // 1.01
System.out.println(round(2.175, 2)); // 2.18
System.out.println(round(5.015, 2)); // 5.02
System.out.println(round(-1.005, 2)); // -1.01
System.out.println(round(-2.175, 2)); // -2.18
System.out.println(round(-5.015, 2)); // -5.02
The code snippet below shows how to display n digits. The trick is to set variable pp to 1 followed by n zeros. In the example below, variable pp value has 5 zeros, so 5 digits will be displayed.
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
If you're using DecimalFormat to convert double to String, it's very straightforward:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
There are several RoundingMode enum values to select from, depending upon the behaviour you require.
DecimalFormat is the best ways to output, but I don't prefer it. I always do this all the time, because it return the double value. So I can use it more than just output.
Math.round(selfEvaluate*100000d.0)/100000d.0;
OR
Math.round(selfEvaluate*100000d.0)*0.00000d1;
If you need large decimal places value, you can use BigDecimal instead. Anyways .0 is important. Without it the rounding of 0.33333d5 return 0.33333 and only 9 digits are allows. The second function without .0 has problems with 0.30000 return 0.30000000000000004.
I have used bellow like in java 8. it is working for me
double amount = 1000.431;
NumberFormat formatter = new DecimalFormat("##.00");
String output = formatter.format(amount);
System.out.println("output = " + output);
Output:
output = 1000.43
the following method could be used if need double
double getRandom(int decimalPoints) {
double a = Math.random();
int multiplier = (int) Math.pow(10, decimalPoints);
int b = (int) (a * multiplier);
return b / (double) multiplier;
}
for example getRandom(2)

Categories

Resources