4

I want to format Java doubles much like String.valueOf(double) does, that is, without loss of precision. But I need to use locale-dependent thousand-separators and would prefer a formatter String, as in String.format. I don't need vertical alignment of several numbers. Examples (in Locale.US):

1.0 -> "1.0"
1.1 -> "1.1"
1.11 -> "1.11"
1000 * Math.PI -> "3,141.592653589793"
1e9 -> "1,000,000,000.0"
1.234567890123e9 -> "1,234,567,890.123"

Any better suggestion than the following hack, involving parsing the result of String.valueOf(d) to calculate the number of decimal places?

double d = ...
String s = String.valueOf(d);
int exponent = s.indexOf('E');
int decimals;
if (0 <= exponent) {
   decimals = Math.max(1, exponent - s.indexOf('.') - Integer.parseInt(s.substring(exponent + 1)) - 1);
}
else {
   decimals = s.length() - s.indexOf('.') - 1;
}
String format = "%,." + decimals + "f";
System.out.printf("Value: " + format + "\n", d);
4
  • DecimalFormat may be a better choice here. Commented Jan 10, 2012 at 12:57
  • If precision is a concern, you should be using java.math.BigDecimal for your calculations. double and float can both lose precision. Commented Jan 10, 2012 at 13:00
  • @jt. I'm not concerned with loss of precision in general (not working with money), only about losing precision relative to the double values. Commented Jan 10, 2012 at 13:42
  • 1
    Since you noted in the comments of ymene's answer that you would like a valid String.format format string, take a look at this question on String.format variable precision. In all likelihood, you're probably not going to get any better than what you already have unless you can remove the String.format restriction and use, for example, NumberFormat. Commented Jan 10, 2012 at 14:23

2 Answers 2

2

Check out DecimalFormat: http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html

Sign up to request clarification or add additional context in comments.

Comments

2

Have a look at NumberFormat or DecimalFormat

For Example:

double d = 1.234567890123e9;

//Initiating a format depending on current locale:
final NumberFormat format = NumberFormat.getInstance();
format.setGroupingUsed( true );
System.out.println( format.format( d ) );

prints:

1,234,567,890.123

But when it comes to precision you might should consider using a different datatype like BigDecimal.

4 Comments

Thanks - I don't need any more precision than that provided by doubles (I'm not working with money). I do need calls to setMin/MaxFractionDigits in addition to setGroupingUsed, but otherwise it behaves as wanted. Except... I can't interoperate with String.format upon which the rest of my code is based :-/
Oh - and NumberFormat behaves differently from String.format on NaN and +/-Infinity.
You are free to extend NumberFormat in any way you want, for example DecimalFormat is also an extension of NumberFormat. Feel free to change its behaviour to your concerns. Unfortunatly I do not understand which kind of interoperation with String.format you are talking about.
I mean solving the problem by finding a suitable format String. I'm working with an API that takes format Strings as arguments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.