4

我试图从edittext中获取值并存储为字符串。然后它转换为双倍。虽然最多可以转换 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

如何在不丢失精度的情况下获得正确的值?

4

4 回答 4

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
于 2013-11-14T08:23:49.060 回答
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。

于 2013-11-14T06:19:13.960 回答
0

尝试这个:

double result = (amount1 * amount2) / 100.0;
string resultInMyFormat =  new DecimalFormat("#.#").format(result);
于 2013-11-14T07:05:15.070 回答
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

看?我从“987654321.45”开始,将其转换为double. 然后用两种不同的方式打印出来。并为相同的获得了两种不同的字符串表示double


那么为什么要这样println(double)打印数字呢?

出色地 ...

  1. System.out是一个PrintStream
  2. println(double)相当于print(double)后面跟着println()
  3. print(double)将 the 转换doubleStringusingString.valueOf(double)
  4. valueOf(double)返回与Double.toString(double)
  5. toString(double)如果数字的大小小于 10 -3或大于或等于 10 7,则指定使用科学计数法。

在各自的 javadocs 中指定。最突出的是用于toString(double).


如果你不相信我,你可以查看 Java 语言规范和浮点表示的 IEE 754 标准;见维基百科

如果你愿意,你甚至可以用它来检查一个值Double.doubleToRawLongBits(double)的位表示。double


最后

经过计算,我得到了4.3827160725E14不正确的正确答案是493827.16

当我重复该计算时,我得到了答案493827.1607250001……使用System.out.println(double). (注意没有科学记数法……因为数字小于 10 7。)

计算的确切答案 (1987654321.45 * 0.05) / 100 493827.160725。确切答案与 Java 给出的答案之间的差异是由计算机浮点舍入误差引起的。发生这种情况是因为 IEE 754 表示实际上是具有二进制尾数和二进制指数的二进制表示,并且因为尾数具有固定数量的二进制精度位数。

这种舍入误差是使用 IEE 754 表示的计算所固有的。如果你想减轻它,你可以用BigDecimal来表示你的数字。但是您应该知道,即使BigDecimal是不精确的:

  • 您不能使用 精确表示 Pi 或任何其他无理数BigDecimal

  • 许多有理数没有精确的表示为BigDecimal; 例如 1.0 / 3.0 的值。

因此,您仍然(理论上)需要关注BigDecimal.

于 2019-01-30T12:24:18.953 回答