Can you explain this output of DecimalFormat API? - java

I have a number with value
0.947
Now, I use DecimalFormat API of java.text with the following pattern and RoundingMode-
double numberToFormat = 0.947;
DecimalFormat restrictTo1DecimalPlace = new DecimalFormat("0.0%");
restrictTo1DecimalPlace.setRoundingMode(RoundingMode.DOWN);
String formattedString = restrictTo2DecimalPlace.format(numberToFormat);
Now, I was expecting the value of formattedString to be 94.7% but its 94.6%.
I know the value has been set to RoundMode.Down but then why does value of following are not rounded down -
0.9471 -> 94.7%
0.9447 -> 94.4%

The closest floating point number to 0.947 is actually
0.94699999999999995292654375589336268603801727294921875
This is what your computer stores as a double when you write 0.947.
Rounding that down gives you 94.6%.
That's life I'm afraid. If you want exact decimal behaviour then use a decimal type! See data type to represent a big decimal in java

Related

NumberFormat doesn't like more than 340 decimal places

I want to format a double with a certain number of decimal places in Java. My code currently looks like this:
final NumberFormat format = NumberFormat.getInstance();
format.setMinimumFractionDigits(decimalPlaces);
format.setMaximumFractionDigits(decimalPlaces);
format.setGroupingUsed(false);
String s = format.format(value);
but when decimalPlaces is more than 340, this method just prints 340 digits and ignores the rest. Is there a way to work around this limitation?
Specifically in my case they're all 0s (and probably would be with any number after a certain point since the precision is not that high) but it seems wrong to me that the function just silently ignores what I want instead of throwing an exception or something.
Yes, I'm aware that a double can't actually hold that many decimal places, but it's also true that an int can't hold any decimal places at all yet I'm able to print it with some.
The documentation of setMinimumFractionDigits contains this statement:
The concrete subclass may enforce an upper limit to this value appropriate to the numeric type being formatted.
Most likely the subclass returned by NumberFormat.getInstance is DecimalFormat, which tells us in the JavaDocs
For formatting numbers other than BigInteger and BigDecimal objects, the lower of newValue and 340 is used. Negative input values are replaced with 0.
So to solve your problem, convert your number to a BigDecimal before formatting it.
In case of double the value is getting truncating. Use/declare value as BigDecimal
Try this sample code:
final NumberFormat format = NumberFormat.getInstance();
format.setMinimumFractionDigits(355);
format.setMaximumFractionDigits(400);
format.setGroupingUsed(false);
System.out.println(format.getMinimumFractionDigits());
BigDecimal bd=new BigDecimal(10L);
String s = format.format(bd);
System.out.println(s.length());
System.out.println(s);

Why Float return different value and how can i solve it, Java

I am using Float to saving value. But when i save it seven and more then value in Float its return me different format value for example..
Float f=1234567.98
then float return me in string
1.23457e+06
What means of this and how can i solve it. Kindly please help me about this
Thanks in Advance
It means one of two things. Either your preferred printing method only shows a certain number of digits by default, or you are requesting more precision than a Float offers. The wikipedia page for single precision floats says that you can expect 6-9 decimal digits will be represented accurately. So that's probably your problem. You should be able to solve it by using a Double to store your value and DecimalFormat to customize the output.
To format a decimal use:
http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html
In this case the format you want is ###.##
An example of using this would be
float f = 123456.78f;
DecimalFormat format = new DecimalFormat("###.##');
String formatted = format.format(f);
Note that if you are using this for monetary calculations you should use BigDecimal instead. Floats are an efficient way of storing real numbers, but they can only represent so many. Here is an example of using BigDecimal:
BigDecimal bd = new BigDecimal(123456.78f);
bd = bd.add(3.4f);
bd = bd.divide(4.3f);//this division with floats may have returned an inexact answer
bd.setScale(2);//Makes sure we only care about 2 decimal places
String strValue = bd.toString();

Java DecimalFormat to double

I'm trying to prevent a java double from printing in scientific notation. I know I can use DecimalFormat for this, but this produces a String. How can I produce an actual double?
I've tried:
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(8);
double n = Double.parseDouble(df.format(z));
However, this still produces a double in scientific notation.
A format is not a property of a double, the data type. This defines just a set of values.
Printing always requires a conversion to a String, so DecimalFormat is fine.
As for using an entirely different set of decimal fractions as values, see java.math.BigDecimal. This is the set of "all" decimal fractions, with a dynamic number of fractional digits, operations and control of round-off.

Converting string to double always gives me wrong representation

I want to convert this string "0.00071942446044" to double by using Double.parsedouble method but it always gives this answer 7.1942446044E-4
Is there any idea to convert it to double but keeping the same number as it is in the string?
Although both numbers are exactly the same, you could use DecimalFormat to manipulate the format in a way you like, only for presentation purpose. Here is an example:
String s = "0.00071942446044";
Double d = Double.parseDouble(s);
DecimalFormat df = new DecimalFormat("#.##############");
System.out.println("double: " + d);
System.out.println("formatted: " + df.format(d));
The out is:
double: 7.1942446044E-4
formatted: 0.00071942446044
Note that the number of # after decimal point is exactly the same as your example.
You can use new BigDecimal(myString), this is not the same but will keep the same representation. It provides API for doing different math, but is slower than doing arithmetical operations with doubles.
It's just a different way of displaying the number. The documentation does a reasonable job of explaining it exactly.
If you simply want to print it in the same format you can use printf or String.format:
Prints 0.000719:
System.out.printf("%f\n", Double.parseDouble("0.00071942446044"));
Prints 0.00071942446044: (with hard-coded precision, which is probably not idea)
System.out.printf("%.14f\n", Double.parseDouble("0.00071942446044"));
Also note that numbers aren't stored in terms of digits, so you won't get an exact large-precision representation for floating point types (float and double) (though double, as you can see can handle this amount of digits). Notice what happens if you use float:
Prints 7.1942444:
System.out.printf("%.7f\n", Float.parseFloat("7.1942446"));
Similar test case for double: (prints 7.1942446044352310)
System.out.printf("%.16f\n", Double.parseDouble("7.1942446044352312"));
If you want greater precision (at a price, obviously - memory and speed), you should use BigDecimal.

Setting precision in Java

If I want a double to have 9 decimal places, do I have to convert it to a string and then back to a double to do this (string methods are the only methods I'm seeing for setting the precision)?. In any case, what is the conventional way for setting the precision for a double if, for example, I want my method to return a double with 9 decimal places.
You're getting confused between a double's internal representation and it's display. Internally double numbers are always stored the same way but you can of course use a formater like DecimalFormat to return 9 decimal points from your double number.
Use Big Decimal to get 9 decimal places
or
double d = 1.2345672626346;
DecimalFormat df = new DecimalFormat("#.#########");
System.out.print(df.format(d));
You can't control precision with primitives in Java. You need to use BigDecimal. Read this excellent tutorial..
You could also use:
DecimalFormat df = DecimalFormat.getInstance(Locale.getDefault());
df.setMinimumFractionDigits(9); //sets 9 digits after the '.'
String formatedString = String.format("%.2f");
it set the presition to 5 digit o any.
if you only want to print it use this way.
System.out.printf("%.5f",123.2342622467);

Categories

Resources