Java如何精确地显示双精度而无法用二进制科学记数法准确表达?

时间:2014-03-20 08:05:59

标签: java double

根据我的理解,在为变量分配任何double值时,它将执行以下步骤:

  1. 转换为二进制。
  2. 做一些科学记谱法的转变。
  3. 转换为IEEE754。
  4. 步骤1和步骤3都可能引入一些不准确之处。因此存储在内存中的值已经不准确了。

    但令人惊讶的是,如果我不对这个双重进行任何计算,只需将其打印出来: println(0.2d)

    甚至

    的println(1245.1325415d)

    只要双倍不长,结果总是准确的。

    将IEEE754格式转换回Base10格式时是否有任何技巧?

3 个答案:

答案 0 :(得分:4)

对于每个双D,有一系列小数部分将转换为D. Double.toString,其中D作为参数产生具有最少有效数字的该范围的成员。通常,"不太长" decimal fraction是其范围的成员,其最高有效数字,因此它是转换为String时获得的数字。

例如:

import java.math.BigDecimal;

public class Test {
  public static void main(String[] args) {
    double d1 = 0.4;
    double d2 = 0.400000000000000000001;
    System.out.println(d1);
    System.out.println(d2);
    System.out.println(new BigDecimal(d1));
  }
}

显示:

0.4
0.4
0.40000000000000002220446049250313080847263336181640625

两者" 0.4"和" 0.400000000000000000001"是在其成员转换为精确值为0.40000000000000002220446049250313080847263336181640625的双精度范围内。 0.4是该范围的最短成员,因此它是toString转换的结果。它也是一个不太长的"小数部分。

答案 1 :(得分:1)

当你调用print时,double会在内部转换为String。

因此,您传递的双倍值将保持与您输入的一样准确。

但是这种转换不是无限制意味着如果你输入6789.78848376767676 ...这将不会完全打印,因为有一些限制。

例如..

System.out.println(67670.65656565656566665);

将输出设为67670.65656565657,因此必须有一些限制来将double表示为String。

所以如果你想检查手动试试这个......

String s=((Double)(67670.65656565656566665)).toString();
System.out.println(s);

这将导致相同的结果。

了解此事的行为TRY THIS

答案 2 :(得分:1)

来自Double.toString()文档:

  

m或a的小数部分必须打印多少位数?必须至少有一个数字来表示小数部分,并且除此之外必须有多个,但只需要多少个,更多的数字来唯一地区分参数值和double类型的相邻值。

底线:格式化程序将输出足够的数字以唯一标识该值。因此,例如,当前导值和后继值分别为0.xxxxx...x49990.xxxxx...x5时,0.xxxxx...x4837的实际值将转换为字符串0.xxxxx...x511。精确的错觉就是:基于偶然事件的错觉。

相关问题