有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java如何精确地显示double,而它不能用二进制科学符号精确地表示?

根据我的理解,当给变量赋值时,它将经历以下步骤:

  1. 转换成二进制
  2. 在科学符号的格式上做一些改变
  3. 转换为IEEE754

第1步和第3步都可能带来一些不准确。所以存储在内存中的值已经不准确了

但令人惊讶的是,如果我没有对这个双精度进行任何计算,只是将其打印出来,就像: println(0.2d)

甚至

println(1245.1325415d)

只要双精度不是太长,结果总是准确的

在将IEEE754格式转换回Base10格式时,有什么技巧吗


共 (3) 个答案

  1. # 1 楼答案

    ^{}文档中:

    How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double.

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

  2. # 2 楼答案

    对于每一个双D,都有一系列十进制分数可以转换为D.double。以D作为参数的toString将生成该范围内有效位数最少的成员。通常,“不太长”的小数是其范围内有效位数最少的成员,因此它是转换为字符串时得到的小数

    例如:

    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转换的结果。它也是一个“不太长”的小数

  3. # 3 楼答案

    调用print时,double在内部转换为String

    这样,您传递的任何双倍值都将与您输入的值一样准确

    但是这种转换不是无限的,如果你输入6789.7884837676。。。由于存在一些限制,这将不会完全打印出来

    例如

    System.out.println(67670.65656565656566665);
    

    67670.65656565657的形式给出输出,所以将double表示为String肯定有一些限制

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

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

    这将产生同样的结果

    了解这东西的行为TRY THIS