问题描述:

If I format a double using the toString method, then I get the full precision of the double. For example (using Scala syntax):

java.text.MessageFormat.format ("{0}", Math.PI.toString)

will result in a string containing:

3.141592653589793

However, this value is not localized. If I pass the double value as a boxed Double, that is as:

java.text.MessageFormat.format ("{0}", Math.PI.asInstanceOf[AnyRef])

(AnyRef is the Scala type that is equivalent to Object in Java), then the result is a localized string with truncated precision:

3.142

The result is the same even if I add more of a hint to the format string:

java.text.MessageFormat.format ("{0,number}", Math.PI.asInstanceOf[AnyRef])

I can get the full precision by specifying a custom format:

java.text.MessageFormat.format ("{0,number,#.###############}", Math.PI.asInstanceOf[AnyRef])

but this requires some knowledge of the double's magnitude and precision. If I'm printing any double value (not just Pi), and want to retain the full precision of the value, then this approach means that I have to dynamically change the format string - and that's not exactly convenient if (as in my case) the format string is actually obtained from a resource bundle.

For example, consider a double value of 1.0e37. Converting to a string first and using "{0}" as the format string results in the appropriate, but unlocalized, string value 1.0E37. If I pass this as a boxed Double with a format string of "{0,number}" then I get the ridiculous value 10,000,000,000,000,000,000,000,000,000,000,000,000.

In short, I can't seem to find a format string that preserves the full precision of a double without first converting it to a string - and that's something I would prefer to avoid like the plague. Is there a number format string that outputs the full precision of a double as a localized value?

UPDATE:

Just to clarify why I would prefer not to have to convert doubles to strings:

  • toString returns, so far as I'm able to tell, a valid Java double literal value. As a string, the result is not localized when passed to MessageFormat.format. For example, say I that I want to output the localized form of the value 1234.567. toString would return "1234.567", and MessageFormat.format would leave it at that. Fine. I have my precision output. However, in Germany, this would make more sense if it appeared as "1.234,567". Even in the US/UK, this would look nicer if it appeared as "1,234.567".
  • If I pass boxed Integer, Boolean, or any other non floating-point primitive type to MessageFormat.format (with a simple "{n}" format), then I get nicely localized, full precision output. I do not need to - and should not, as I'll lose localized output - convert these values to strings first. This means that I have to treat doubles (and floats and BigDecimals) differently and convert them to strings before passing them to MessageFormat.format. (Moreover, I have to remember to do that every time.)

网友答案:

MessageFormat uses an localized representation, with thousands separators, maybe decimal comma and so on. In your usage it uses the default locale of your platform.

Something one should keep separate from the universal programmer's notation, valueOf/toString.

Using double and precision is a bit of an oxymoron, as the decimal representation is an approximation of the sum of powers of 2 that a double is internally.

To keep the full information you could store the raw bits in a textual form, using Double.doubleToRawLongBits and on the way back longBitsToDouble.

double x = Math.PI;
String repr = String.format("%016x", Double.doubleToRawLongBits(x));
x = Double.longBitsToDouble(Long.valueOf(repr, 16));
网友答案:

Double format in Java is represented by 64 bits, 52 bits are used for the mantissa. log(252) = 15.65355977. This means that the precision of Double is roughly 15-16 digits.

So I think that the result 3.141592653589793 is pretty much everything you are able to get from Double.

相关阅读:
Top