Android-避免字符串中的指数转换为双精度转换
我试图从edittext中获取值并将其存储为字符串。然后它转换为双精度。转换最多7个字符时功能正常,但如果我尝试添加7个以上的字符,结果是1.23456789E8。这是我的密码Android-避免字符串中的指数转换为双精度转换,android,string,double,type-conversion,Android,String,Double,Type Conversion,我试图从edittext中获取值并将其存储为字符串。然后它转换为双精度。转换最多7个字符时功能正常,但如果我尝试添加7个以上的字符,结果是1.23456789E8。这是我的密码 String value = txtData.txtSearch.getText().toString(); // value = "987654321.45" double amount1 = Double.parseDouble(value); // amount1 = 9.8765432145E8 double
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
如何在不损失精度的情况下获得正确的值?以下代码给出了您的预期结果:
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。试试以下方法:
double result = (amount1 * amount2) / 100.0;
string resultInMyFormat = new DecimalFormat("#.#").format(result);
我解决了。我使用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
如何避免字符串中的指数转换为双精度转换
我想我们都没有抓住要点
以下是您的示例:
// value = "987654321.45"
double amount1 = Double.parseDouble(value);
// amount1 = 9.8765432145E8
大概,评论中的内容是打印出来的;e、 g.使用调试器或调用println
那么为什么你会看到指数/科学符号呢
这并不是因为字符串被解析为双精度的方式。实际上,当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
看到了吗?我从“987654321.45”开始,将其转换为双精度。然后用两种不同的方式打印。对于相同的double
值,得到了两种不同的字符串表示形式
那么为什么println(double)
会这样打印数字呢
嗯
System.out
是一个PrintStream
println(double)
相当于print(double)
后跟println()
print(double)
使用String.valueOf(double)
valueOf(double)
返回与double.toString(double)
toString(double)
指定在数字大小小于10-3或大于或等于107时使用科学记数法
这些都在各自的Javadoc中指定。最突出的是fortoString(double)
如果你不相信我,你可以检查Java语言规范和IEE754标准的浮点表示法;看
如果愿意,甚至可以使用Double.Double或awlongbits(Double)
检查Double
值的位表示
最后
经过计算,我得到了不正确的4.3827160725E14
,正确答案是493827.16
当我重复计算时,我得到了答案493827.1607250001
。。。使用System.out.println(双精度)
。(请注意,没有科学符号……因为数字小于107。)
计算的准确答案(1987654321.45*0.05)/100 493827.160725。精确答案与Java给出的答案之间的差异是由计算机浮点舍入误差造成的。之所以会出现这种情况,是因为IEE 754表示法实际上是具有二进制尾数和二进制指数的二进制表示法,而且尾数具有固定数量的精度二进制数字
这种舍入误差是使用IEE 754表示法进行计算时固有的。如果你想减轻它,你可以用BigDecimal
来表示你的数字。但您应该知道,即使是BigDecimal
也不精确:
- 不能使用
BigDecimal
精确表示Pi或任何其他无理数
- 许多有理数没有一个精确的表示形式,即
BigDecimal
;e、 g.1.0/3.0的值
因此,您(理论上)仍然需要关注BigDecimal
尝试long而不是double的舍入错误