Converting string to double always gives me wrong representation - java

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.

Related

Can you explain this output of DecimalFormat API?

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

How to convert money representation of different currency to a decimal value in java

Suppose I have money value represented as 10.000,00 in congo currency and I want it to be converted to a decimal amount like 10000.00. The money representation can be any from deferent countries and the outcome should be a decimal amount.
How do I achieve this in java?
It is better to keep money in integer format in minimal possible coin value - f.e. in US dollars - if you have 1$ and 25 cents - just save it as int 125 cents - it helps to avoid very common problems with java float/doubles precision errors.
You can use replace for example :
money.replace(",", "#").replace(".", "").replace("#", ".")
This will gives you:
10000.00
If you want to get the decimal value then you can use :
String money = "10.000,00";
NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
Number number = format.parse(money.replace(".", ""));
System.out.println(number);
double d = number.doubleValue();
System.out.println(d);
This will gives you:
10000.0
The method NumberFormat.getCurrencyInstance(Locale)
is made exactly for this purpose.
It takes care for all country-specific formatting (decimal point or comma, currency name, currency before or after number, thousands grouping, ...).
You use it like this, for example for Congo (Democratic Republic):
Locale locale = new Locale("", "CD");
NumberFormat currencyFormat= NumberFormat.getCurrencyInstance(locale);
String s = currencyFormat.format(10000.0);
Result is "CDF 10,000.00"
Note: For the following, I assume it will not necessarily be known beforehand which currency/locale to expect.
I did that just recently like this: Split the string by all possible markers (.,' should be enough). Then join the parts except for the last one. Before you add that, you add whatever decimal-sign you need. So, "10.000,00" => [[10],[000],[00]] => 10000.00. This can then be converted to BigDecimal.
(Don't use float or double for monetary values.)
The reason for doing it that way: You can handle most formats like
1.234,56
1,234.56
1'234.56
1234.567
And you automatically can handle numbers of fraction digits != 2.
You'd only have to be careful with whitespaces and currencies with no fractions (split array will be of size = 1). Also be careful with currencies with 3 fraction digits. It can be cumbersome to tell amounts apart using this approach that are not using a decimal at all and those that do ("1.234" =>"1234.000" and "1.234,567" => "1234.567"). You might need a little additional validation & correction for those cases.
I don't know if that's interesting for you, but Java 8 has a Currency class, that can give you number of fraction digits.
I also suggest writing a unit test, so you can be sure all expected input formats will end up in your desired format. And of course I suggest extensive documentation of what formats are accepted / allowed.

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);

Java division for double and float without E

I'm doing some large number divisions (long/long to double, and int/int to float).. But I bump, to a problem when the results include the "E". I know we can use NumberFormat to format when displaying, but that's not what I. Just want the result of the divisions to not involve the "E", i.e. just round it up to the closest float/double that fits in the space.
Anybody got an idea?
The internal representation of floating point number does not have a switch for E presence or not (check IEEE-754). So your float/double number is just number (not a number with E or without it).
The only place where you get E is when you print this value out. And while Java uses number formater for printing, so I don't see a point why you don't want to use it here.
System.out.println(new DecimalFormat("#.#####").format(doubleValue));
The general problem that double and float in binary format. It not always possible to convert decimal fraction to binary fraction. For example 0.2 decmal fraction have infinitely many digits in binary (double) format. So whe converted from bynary format to decimal string, it result something like "0.2000000001" what displayed with E. To solve this problem you can use BigDecimal class what contains number in decimal format, so no E problem - it can easy rounded to any decimal point by setScale method. Or you can sore double as is, an write it to output by String.format("My value are: %.3f", value) - i recommend this way.
If you just want round you value to decimal point you can use:
new BigDecimal(val).setScale(3, RoundingMode.HALF_EVEN).doubleValue()
But there no any garanty what this core return double with fine fraction numbers.

What is decimal format exactly doing?

This is my code:
float result=(float) ( (new Float(result1)*0.3)+(new Float(result2)*0.7));
String a=dec.format(result);
vprosvasis.setText(a);
If I use vprosvasis somewhere else in my app, it will have the price a.
For example, if my result is 12,34, a will be 12,3 so vprosvasis will be 12,3 if I write
float genikosvathmos = ((new Float(vprosvasis.getText().toString()) +
new Float(vprosvasis2.getText().toString()) +
new Float(vprosvasis3.getText().toString()) +
new Float(vprosvasis4.getText().toString()) +
new Float(vprosvasis5.getText().toString()) +
new Float(vprosvasis6.getText().toString())) / 6);
Would suggest using primitives (specifically, double) rather than Object wrappers (unless you have some need that you're not showing here).
Then look at the Double javadoc, especially the static utility methods:
http://download.oracle.com/javase/6/docs/api/java/lang/Double.html
double myDouble = Double.parseDouble(myString);
String s = Double.toString(myDouble);
The purpose of DecimalFormat is to format numbers as text in a locale-specific way. (It can also be used to parse a locale-specific number format to a suitable Number type.) For example, in the American English locale, a period ('.') is used as a decimal point, rather than a comma (',').
It is important to note that the String produced by a DecimalFormat is very likely to be incompatible with the format required for the Float(String) constructor. The string format consumed by Float is not locale-specific; it is a fixed format that is the same as that specified by the Java Language Specification for float literals in Java source code.
If you are doing calculations with money, don't use a floating-point type like float or double. Use instances of java.math.BigDecimal instead. This type performs exact arithmetic, and when rounding is performed, you can control the rounding to conform with your accounting practices.
Like Daniel, I'm not quite sure what you're trying to get from this post. But I will answer the question you asked in your title at face value.
You don't include the code where dec is declared, or any code where it's operated on, but from context it seems to be an instance of the DecimalFormat class. If so, it's taking result, which is a float, and doing the following things:
widening it to long
using the method format(double number) inherited from NumberFormat to get the String representation of result
storing the result in a

Categories

Resources