views:

35094

answers:

10

What I'd 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 a 5, it always rounds up the previous number. This is the standard method of rounding most people expect in most situations.

I also would like only significant digits to be displayed. That is 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?

+7  A: 

Assuming value is a double, you can do:

(double)Math.round(value * 100000) / 100000

That's for 5 digits precision. The number of zeros indicate the number of decimals.

asterite
Math.round uses an internal cast to long, which you are then casting back to double.
chris
I know... If you find out that this particular solution is a performance bottleneck for your system, please let me know ;)
asterite
lmao ... I'm so glad I read comments :)
_ande_turner_
I'm paid by clock cycle -- it could be important.
chris
+2  A: 
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
chris
A: 

maybe this pseudocode will do the trick.

format((round(r*10^desired_number_of_digits)/10^desired_num...))

Mastermind
+15  A: 

Use setRoundingMode, see linked Javadoc, set the rounding mode explicitly to handle your issue with the half-even round, then use the format pattern for your required output.

curtisk
This is probably the best solution presented so far. The reason I didn't spot this facility when I first looked at the DecimalFormat class is that it was only introduced in Java 1.6. Unfortunately I'm restricted to using 1.5 but it will be useful to know for the future.
Alex Spurling
A: 

Agreed with all above, round it with Math.Round as a number, then cast to a string, that will take care of trailing zeros (i.e. .912300 will be ".9123" at the end

Fry
+3  A: 

You can also use the

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

to make sure you have the trailing 0's.

Milhous
+3  A: 

new BigDecimal(String.valueOf(doubleVar)).setScale(yourScaleHere, BigDecimal.ROUND_HALF_UP); will get you a BigDecimal. To get the string out of it, just call that BigDecimal's toString method.

MetroidFan2002
That's my preferred solution.Even shorter:BigDecimal.valueOf(doubleVar).setScale(yourScaleHere, BigDecimal.ROUND_HALF_UP);BigDecimal.valueOf(double val) actually calls Double.toString() under the hood ;)
eneveu
A: 

In Java you could write this code, it takes care of negative numbers too.

Carefull when using this! Java cannot represent float/double precisely, you really should use BigDecimal instead!

Concerning the following snippet : Obviously x * 100 might overflow if the value of x is near Double.POSITIVE_INFINITY or Double.NEGATIVE_INFINITY, but like everything it's a trade-off, so use it with this trade-off in mind.

double truncate(double x) {
    if ( x > 0 )
         return Math.floor(x * 100) / 100;
    else
         return Math.ceil(x * 100) / 100;
}
Brice
+1  A: 

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();
Ovesh
A: 

And what do I need to do when I don't want the trailing zeroes? I want a formatting like this:

 123
   4,5
  26,65
9999,53

Thanks!

Joris