Reputation: 1949
I trying to get value from edittext and stored as string. Then it converts to double. While converting up to 7 characters functioning normally but if i try to add more than 7 result is 1.23456789E8. Here is my code
String value = txtData.txtSearch.getText().toString();
// value = "987654321.45"
double amount1 = Double.parseDouble(value);
// amount1 = 9.8765432145E8
double amount2 = 0.05;
double result = (amount1 * amount2) / 100;
// result = 4.3827160725E14
after calculation i got 4.3827160725E14 which is not correct correct answer is 493827.16
How can i get correct value without losing precision?
Upvotes: 4
Views: 3345
Reputation: 109
if anyone is looking for vice versa, if you first convert to BigDecimal and then PlainString. By doing that you keep your expected double. e.g.
val yourDouble = -6.9452331E-4
val bigDecimal = yourDouble.toBigDecimal()
//bigDecimal = -0.00069452331
val stringDecimal = bigDecimal.toPlainString()
//stringDecimal = "-0.00069452331"
Upvotes: 0
Reputation: 718936
How do you avoid exponential in string to double conversion?
I think we are all missing the point here.
Here is your example:
// value = "987654321.45"
double amount1 = Double.parseDouble(value);
// amount1 = 9.8765432145E8
Presumably, the stuff in comments was printed; e.g. using a debugger or calls to println
.
So why are you seeing exponential / scientific notation?
Well it is NOT due to the way that the string was parsed to a double
. It is actually happening when the double
is converted back to a string in order to print it. Example:
$ cat Test.java
import java.text.DecimalFormat;
public class Test {
public static void main(String[] args) {
String value = "987654321.45";
double amount = Double.parseDouble(value);
System.out.println(amount);
DecimalFormat format = new DecimalFormat("0.########");
System.out.println(format.format(amount));
}
}
$ java Test
9.8765432145E8
987654321.45
See? I started with "987654321.45", converted it to a double
. Then printed it two different ways. And got two different string representations for the same double
value
So why does println(double)
print the number like that?
Well ...
System.out
is a PrintStream
println(double)
is equivalent to print(double)
followed by println()
print(double)
converts the double
to a String
using String.valueOf(double)
valueOf(double)
returns the same representation as Double.toString(double)
toString(double)
is specified to use scientific notation if the magnitude of the number is less than 10-3 or greater or equal to 107.This is all specified in the respective javadocs. The most salient is the javadoc for toString(double)
.
If you don't believe me, you can check the Java Language Specification, and the IEE 754 Standard for floating point representations; see Wikipedia.
If you want to, you can even use Double.doubleToRawLongBits(double)
to examine the bit representation of a double
value.
Finally
After calculation i got
4.3827160725E14
which is not correct correct answer is493827.16
.
When I repeat that calculation I get the answer 493827.1607250001
... using System.out.println(double)
. (Note that there is no scientific notation ... because the number is less than 107. )
The exact answer for the calculation (1987654321.45 * 0.05) / 100 493827.160725. The difference between the the exact answer and what Java gives us is caused by computer floating point rounding error . It happens because the IEE 754 representation is actually binary representation with a binary mantissa and a binary exponent, and because the mantissa has a fixed number of binary digits of precision.
This rounding error is inherent to calculations using IEE 754 representations. If you want to mitigate it, you can use BigDecimal
to represent your numbers. But you should be aware that even BigDecimal
is not precise:
You can't represent Pi or any other irrational number precisely using BigDecimal
.
Many rational numbers don't have a precise representation as a BigDecimal
; e.g. the value of 1.0 / 3.0.
So you still (in theory) need to be concerned with rounding errors with BigDecimal
.
Upvotes: 0
Reputation: 1949
I solved it. i use BigDecimal instead of double now my code is
String value = txtData.txtSearch.getText().toString();
// value = "987654321.45"
BigDecimal amount1 = new BigDecimal(value);
// amount1 = "987654321.45"
BigDecimal amount2 = new BigDecimal(0.05);
BigDecimal result = (amount1.multiply(amount2)).divide(new BigDecimal(100));
result = result.setScale(2, RoundingMode.FLOOR);
// result = 493827.16
Upvotes: 3
Reputation: 667
try this:
double result = (amount1 * amount2) / 100.0;
string resultInMyFormat = new DecimalFormat("#.#").format(result);
Upvotes: 0
Reputation: 30088
The following code gives your expected result:
public class DoubleTest {
public static void main(String[] args) {
double amount1 = Double.parseDouble("987654321.45");
double amount2 = 0.05;
double result = (amount1 * amount2) / 100;
System.out.println(result);
}
}
So, are you sure that you're getting the value that you think you are from txtData.txtSearch.getText().toString();
?
By the way, if you're really interested in arbitrary precision (e.g. when dealing with money), use BigDecimal.
Upvotes: 0