【问题标题】:How to determine the max precision for double如何确定双精度的最大精度
【发布时间】:2016-03-31 22:11:41
【问题描述】:

我正在尝试确定双精度的最大精度是多少。在此链接中接受答案的 cmets Retain precision with double in Java@PeterLawrey 声明最大精度为 15。

你如何确定这一点?

【问题讨论】:

标签: java floating-point double precision


【解决方案1】:

@PeterLawrey 声明最大精度为 15。

这实际上根本不是他所说的。他说的是:

double 精确到小数点后 15 位

他错了。它们有 15 位小数数字的准确度。

任何数的小数位数由它的log给出,以10为底。15是log的底值10(253-1),其中 53 是尾数的位数(包括隐含位),如 Javadoc 和 IEEE 754 中所述,因此 253-1 是最大可能的尾数值。实际值为 15.954589770191003298111788092734 到 Windows 计算器的限制。

他将其描述为“精确的小数位”是完全错误的。 double 有 15 个小数数字的准确度如果它们都在小数点之前。对于带有小数部分的数字,您可以得到多于 15 位的十进制表示,因为十进制和二进制分数的不可通约性。

【讨论】:

  • 谢谢澄清了一点。但是 2^53 最大尾数值是否意味着 15 位数字?
  • 任何数字的小数位数由其对数给出,以 10 为底。
  • “直对数参数”仅适用于整数,这可能就是您在上一段中所说的。对于浮点,您必须像我在这里所做的那样进行推导:exploringbinary.com/…。对于双打,您会得到相同的答案(15);对于浮点数,log_10(2^24-1) 约为 7.22,但最大精度为 6。(另见 stackoverflow.com/questions/30688422/…。)
  • @RickRegan 为什么浮点数的最大精度是 6 而不是 & ?
  • 作为我之前评论的后续...我写了一篇专门解决这个问题的文章:exploringbinary.com/…@ShivamSinha
【解决方案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值。见en.wikipedia.org/wiki/Machine_epsilon(看表中的binary64行)
  • 他问的是浮点精度本身,而不是 epsilon,他特别问的是值 15,你根本没有解决这个问题。
  • 我用十进制解释:如果你有4位精度,你可以表示1.0000 - 0.0001,但你不能表示数字1.00000-0.00001。在此示例中,精度为 4 位小数,epsilon 为 0.0001。 epsilon 直接测量浮点精度。只需转置为二进制。 (注意:我的结果的指数是1.11E-16 表示精度约为15位)
  • 你应该在你的答案中解释所有这些,但小数部分的位数告诉你什么。您打印的有 17 个十进制数字。
  • 答案是不是它打印的小数位数。答案是值 (-16) 的指数。我将删除一些数字以消除混乱。
【解决方案3】:

你也可以直接“测量”它:

for(double d = 1 ; d > 0 ; d/=2) System.out.println(d);

这段代码的想法是用一位来达到最小的数字。因此,您从1(只有 1 位)开始并除以 2(在二进制中向右移动位),直到到达最后一位。此循环打印的最后一个数字是:

4.9E-324

【讨论】:

  • 这如何表明双精度数具有 15 位精度?
  • 双精度可表示的最小值与其最大精度无关。一个是指数宽度的函数,另一个是尾数宽度的函数。
【解决方案4】:

double的最大精度是第一个大于0的值。根据Double的Javadoc,这个数字用Double.MIN_VALUE表示。可以这样输出:

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

有关示例,请参阅 this IDEOne program

【讨论】:

  • 我认为这不是真的。我相信 OP 想知道在双精度中有意义的有效数字的确切数量。最小可能(绝对)双精度值就是负指数部分最大和数字部分最小的那个。
  • 您将精度与范围混淆了,就像这里的其他几个答案一样。
猜你喜欢
  • 1970-01-01
  • 2015-06-05
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
  • 2014-05-28
  • 2019-07-13
  • 1970-01-01
相关资源
最近更新 更多