如何确定double类型的最大精度

17

我试图确定double类型的最大精度。在此链接Retain precision with double in Java的被接受回答的评论中,@PeterLawrey表示最大精度为15。

如何确定这一点?


3
你看过重复问题中的维基链接了吗?Java使用IEEE 754浮点双精度。 - Darth Android
4个回答

14
@PeterLawrey说最高精度为15位小数。实际上他所说的是:“双精度”有15个小数位的精度。”而他是错误的。它们具有15位小数的数字精度。 任何数字中的小数位数由其以10为底的对数给出。 15是log10(253-1)的floor值,其中53是尾数的位数(包括隐含位),如Javadoc和IEEE 754所述,253-1是因此最大可能的尾数值。 对于Windows计算器来说,实际值为15.954589770191003298111788092734。如果所有数字都在小数点之前,则double具有15个小数位的精度。对于具有小数部分的数字,您可以获得比15位更多的小数位表示,因为十进制和二进制分数的不可比性。

谢谢,这有点澄清了。然而,2^53的最大尾数值是否意味着15位数字? - Shivam Sinha
任何数字的小数位数由其以10为底的对数给出。 - user207421
2
“直接对数论证”仅适用于整数,这也许是您在最后一段中所说的。对于浮点数,您必须像我在这里做的那样进行推导:http://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/。对于双精度浮点数,您会得到相同的答案(15);对于单精度浮点数,log_10(2^24-1)约为7.22,但最大精度为6。(还请参见https://dev59.com/LV0a5IYBdhLWcg3wH1ly。) - Rick Regan
@RickRegan 为什么浮点数的最大精度是6而不是&? - Shivam Sinha
@ShivamSinha 我认为这在我的评论中的两个链接中有解释。 - Rick Regan
1
作为对我之前评论的跟进...我写了一篇专门解决这个问题的文章:http://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ @ShivamSinha - Rick Regan

2

运行这段代码,观察它在哪里停止。

public class FindPrecisionDouble {
  static public void main(String[] args) {
    double x = 1.0;
    double y = 0.5;
    double epsilon = 0;
    int nb_iter = 0;
    while ((nb_iter < 1000) && (x != y)) {
        System.out.println(x-y);
        epsilon = Math.abs(x-y);
        y = ( x + y ) * 0.5;
    }
    final double prec_decimal = - Math.log(epsilon) / Math.log(10.0);
    final double prec_binary = - Math.log(epsilon) / Math.log(2.0);
    System.out.print("On this machine, for the 'double' type, ");
    System.out.print("epsilon = " );
    System.out.println( epsilon );
    System.out.print("The decimal precision is " );
    System.out.print( prec_decimal );
    System.out.println(" digits" );
    System.out.print("The binary precision is " );
    System.out.print( prec_binary );
    System.out.println(" bits" );
  }
}

变量y变为与1.0不同的最小值。在我的电脑上(Mac Intel Core i5),它停在1.1102...E-16。然后它打印出精度(十进制和二进制)。
https://en.wikipedia.org/wiki/Machine_epsilon中所述,浮点精度可以用epsilon值估计。它是“将最小数字添加到1中,得到与1不同结果的数字”(我做了一个小变化:1-e代替1+e,但逻辑相同)
我将在十进制中解释:如果您具有4个小数点的精度,则可以表示1.0000-0.0001,但无法表示数字1.00000-0.00001(缺少第5个小数)。在此示例中,使用4个小数点的精度,epsilon为0.0001。epsilon直接测量浮点精度。只需转换为二进制即可。 编辑 您的问题问“如何确定...”。您正在寻找的答案更多是解释而不是确定精度的方法(使用您接受的答案)。无论如何,对于其他人来说,在计算机上运行此代码将确定“double”类型的精度。

它试图寻找与浮点精度相关联的epsilon值。请参阅https://en.wikipedia.org/wiki/Machine_epsilon(查看表中的binary64行) - Sci Prog
他在询问浮点精度本身,而不是epsilon,并且他特别在询问值15,而你根本没有回答。 - user207421
我来用通俗易懂的语言解释一下:如果你有四位小数的精度,你可以表示出1.0000 - 0.0001这个数字,但是你无法表示出1.00000-0.00001这个数字。在这个例子中,使用四位小数的精度,epsilon为0.0001。epsilon 直接 衡量了浮点精度。只需要转换成二进制即可。(注意:我的结果指数为1.11E-16表明精度约为15位) - Sci Prog
你应该在你的回答中解释所有这些,但是十进制小数的位数并不能告诉你任何有用的信息。你打印出来的那个有17位小数。 - user207421
答案不是它打印的小数位数。答案是该值的指数(-16)。我会移除一些数字以消除混淆。 - Sci Prog
你需要在回答中解释清楚这一点。但是你提供的只是一个迭代解决方案,而且解释得很差。 - user207421

-1

双精度浮点数 double 的最大精度是第一个大于 0 的值。根据 Double 的 Javadoc,这个数字由 Double.MIN_VALUE 表示。你可以按如下方式输出它:

BigDecimal doubleMinVal = BigDecimal.valueOf(Double.MIN_VALUE);
System.out.println(doubleMinVal.toPlainString());
System.out.println(doubleMinVal.toString());

请参考这个IDEOne程序作为示例。


1
我不认为那是正确的。我相信OP想知道一个double中有多少个有效数字。最小的(绝对值)double值仅是具有最大负指数部分和最小数字部分的值。 - Paul
你正在混淆精度和范围,就像其他几个答案在这里一样。 - user207421

-1
你也可以直接“测量”它:
for(double d = 1 ; d > 0 ; d/=2) System.out.println(d);

这段代码的思路是通过一个单一位来达到最小数。因此,你从1开始(只有1个位),然后除以2(在二进制中向右移位)直到达到最后一位。这个循环打印的最后一个数字是:

4.9E-324


4
这怎么表明双精度浮点数具有15位有效数字? - assylias
3
双精度浮点数中可表示的最小值与其最大精度完全无关。一个是指数位宽的函数,另一个是尾数位宽的函数。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接