我试图从edittext获取值并存储为字符串。然后它转换为double。虽然转换最多7个字符正常运行,但如果我尝试添加超过7个结果是1.23456789E8。这是我的代码
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
计算后得到4.3827160725E14这是不正确的正确答案是493827.16
如何在不丢失精度的情况下获得正确的值?
答案 0 :(得分:3)
我解决了。我现在使用BigDecimal而不是double,我的代码是
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
答案 1 :(得分:0)
以下代码给出了您的预期结果:
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);
}
}
那么,你确定你从txtData.txtSearch.getText().toString();
获得了你认为的价值吗?
顺便说一句,如果你真的对任意精度感兴趣(例如在处理金钱时),请使用BigDecimal。
答案 2 :(得分:0)
试试这个:
double result = (amount1 * amount2) / 100.0;
string resultInMyFormat = new DecimalFormat("#.#").format(result);
答案 3 :(得分:0)
如何避免将字符串以指数形式转换为双精度?
我想我们都错了。
这是您的示例:
// value = "987654321.45"
double amount1 = Double.parseDouble(value);
// amount1 = 9.8765432145E8
大概是评论中的内容被打印了;例如使用调试器或调用println
。
那你为什么看到指数/科学记号?
好吧,这不是由于字符串解析为double
的方式所致。实际上,将double
转换成字符串以进行打印时,$ 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
就发生了。示例:
double
看到了吗?我从“ 987654321.45”开始,将其转换为double
。然后以两种不同的方式打印它。并为相同的println(double)
值得到了两个不同的字符串表示形式
那为什么System.out
这样打印数字?
好吧...
PrintStream
是println(double)
print(double)
等效于println()
,后跟print(double)
double
使用String
将String.valueOf(double)
转换为valueOf(double)
Double.toString(double)
返回与toString(double)
相同的表示形式toString(double)
以使用科学计数法这是在各自的javadocs中指定的 all 。最突出的是Double.doubleToRawLongBits(double)
的{{3}}。
如果您不相信我,可以查看Java语言规范和IEE 754标准中的浮点表示形式。参见javadoc。
如果需要,甚至可以使用double
来检查4.3827160725E14
值的位表示形式。
最后
计算后,我得到
493827.16
,这是不正确的,正确答案是493827.1607250001
。
当我重复该计算时,使用System.out.println(double)
得到答案BigDecimal
...。 (请注意,没有科学计数法,因为该数字小于10 7 。)
计算的确切答案(1987654321.45 * 0.05)/ 100 493827.160725。确切答案与Java给我们的答案之间的差异是由计算机浮点数舍入误差引起的。之所以会发生这种情况,是因为IEE 754表示形式实际上是具有二进制尾数和二进制指数的二进制表示形式,并且因为该尾数具有固定数量的精度二进制数字。
此舍入误差是使用IEE 754表示进行计算所固有的。如果要减轻它的影响,可以使用BigDecimal
来代表您的数字。但是您应该意识到,即使BigDecimal
也不是精确的:
您无法使用BigDecimal
精确表示Pi或任何其他非理性数字。
许多有理数没有精确表示为BigDecimal
;例如1.0 / 3.0的值。
因此,从理论上讲,您仍然需要关注0.sqltable | 1.df
的舍入错误。