【问题标题】:How many significant digits do floats and doubles have in java?java中的浮点数和双精度数有多少位有效数字?
【发布时间】:2012-11-24 16:09:52
【问题描述】:

浮点数有 32 位二进制数,双精度数有 64 位二进制数吗?文档太难理解了。

所有位都转换为有效数字吗?还是小数点的位置占用了一些位?

【问题讨论】:

  • 所有这些位都转换为有效数字吗?还是小数点的位置占用了一些位?
  • @user1774214 浮点数根本不像整数那样编码。看看我给的链接。例如,您必须了解精度不统一。
  • @dystroy 我不确定您所说的“精度不统一”是什么意思。除非您指的是非规范化,否则它的精度非常一致,为 53 位和 24 位。
  • @PascalCuoq 对于较小的数字,精度更高。随着指数的变化(或点浮动),尾数保持代表相同数量的数字。因此,如果数字很大,尾数“无法达到”较低的有效数字,从而降低精度。
  • @Virtuel 精度为 53 位。 就是我们所说的精度。您似乎在考虑绝对准确度之类的。

标签: java floating-point


【解决方案1】:

float32 位(4 个字节),其中 23 位 用于尾数(大约 7 个十进制数字)。 8 位用于指数,因此浮点数可以使用这 8 位将小数点向右或向左“移动”。这样做可以避免在尾数中存储大量零,如 0.0000003 (3 × 10-7) 或 3000000 (3 × 107)。有 1 位用作符号位。

double64 位(8 字节),其中 52 位 用于尾数(大约 16 位十进制数字)。 11位用于指数,1位为符号位。

由于我们使用二进制(只有 0 和 1),所以当数字非零时,尾数中的一位隐含为 1(浮点数和双精度数都使用此技巧)。

此外,由于所有内容都是二进制(尾数和指数),因此转换为十进制数通常不准确。像 0.5、0.25、0.75、0.125 这样的数字被精确存储,但 0.1 不是。正如其他人所说,如果您需要精确存储美分,请不要使用 float 或 double,使用 int、long、BigInteger 或 BigDecimal。

来源:

http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers

http://en.wikipedia.org/wiki/Binary64

http://en.wikipedia.org/wiki/Binary32

【讨论】:

  • 6 到 9 是什么意思?它怎么能改变?因此,如果我多次运行一些具有 8 个十进制数字(如 0.000000001)的代码,我会得到不同的结果吗?你是这个意思吗?
  • 有些数字可以比其他数字更准确地表示为二进制。您可以看到 0.125(1/8,8 是 2 的幂)和 0.1(1/10,10 不是 2 的幂)的差异。前者有更多(十进制)数字,但表示精确。因此,一个 6 位小数的数字可能比另一个 8 位数字具有更大的舍入误差。
  • double 为 15.9 个十进制数字,float 为 7.2 个十进制数字,即 15 和 7。在每种情况下都可以表示一些更大的数字,但它们都不适用于分数,但有这不是“平均水平”,您的消息来源也没有其他说法。
  • 如果您不喜欢“平均”这个词,请提出修改建议。它一开始不是我添加的,而是由其他人编辑的……(我真的没有看到需要编辑)。
  • 有趣的是,实际上比存储在尾数/有效数字中的精度多一位。分别为 float 和 double 存储 23 位和 52 位,但由于数字已标准化,我们可以假设前导 1 位,然后将其省略。这就是有效精度分别为 24 位和 53 位的原因。精确的小数精度计算 log10(2^24) = 7.22 和 log10(2^53) = 15.95
【解决方案2】:

32 位浮点数大约有 7 位精度,64 位双精度大约有 16 位精度

长答案:

浮点数包含三个部分:

  1. 一个符号位,用于确定数字是正数还是负数。
  2. 指数,用于确定数字的大小
  3. 一个分数,它确定两个指数值之间的距离 是。这有时称为“the significand, mantissa, or coefficient”

基本上,这适用于sign * 2^exponent * (1 + fraction)。规模” 这个数字的指数,与我们无关,因为它只是缩放 分数部分的值。知道log₁₀(n) 给出了 n 的数字,† 我们可以确定浮点数的精度 与log₁₀(largest_possible_fraction)。因为浮点数中的每个位存储 2 可能性,n 位的二进制数可以存储最多 2ⁿ - 1 的数字(a 2ⁿ values 的总数,其中一个值为零)。这有点 毛茸茸的,因为事实证明浮点数是用一个存储的 比他们可以使用的分数少,因为零是专门表示的 并且所有非零数都至少有一个非零二进制位。‡

结合这一点,浮点数的精度位数是 log₁₀(2ⁿ),其中n 是浮点数的位数 分数。一个 32 位浮点数有 24 位小数,对应 ≈7.22 个十进制数字 精度,并且 64 位双精度有 53 位小数,约 15.95 个十进制数字 精度。

有关浮点精度的更多信息,您可能需要阅读 machine epsilon


† 至少对于n ≥ 1 - 对于其他数字,您的公式看起来更像 ⌊log₁₀(|n|)⌋ + 1.

‡ “这条规则被称为前导位约定,隐含位 约定,或隐藏位约定。” (Wikipedia)

【讨论】:

    【解决方案3】:

    来自java specification

    浮点类型有float和double,概念上是 与单精度 32 位和双精度相关联 IEEE 中指定的 64 位格式 IEEE 754 值和操作 二进制浮点算术标准,ANSI/IEEE 标准 754-1985(IEEE,纽约)。

    如果不了解 IEEE754 基础知识,就很难用数字做任何事情,这里是another link

    重要的是要了解精度不是统一的,并且这不是对整数的精确存储。

    一个例子:

    double a = 0.3 - 0.1;
    System.out.println(a);          
    

    打印

    0.19999999999999998
    

    如果您需要任意精度(例如出于财务目的),您可能需要Big Decimal

    【讨论】:

      【解决方案4】:

      一个普通的数学答案。

      了解浮点数实现为一些位表示指数,其余的,大多数为数字(在二进制系统中),有以下情况:

      如果指数较高,例如 10²³,如果最低有效位发生变化,则两个相邻可区分数字之间会出现很大差异。此外,以 2 为底的小数点使得许多以 10 为底的数字只能近似; 1/5、1/10 是无穷无尽的数字。

      所以在 general 中:如果您关心有效数字,则不应使用浮点数。对于具有计算 e,a 的货币金额,最好使用 BigDecimal

      physics 浮点 doubles 就足够了,floats 几乎没有。此外,处理器的浮点部分 FPU 甚至可以在内部使用更高的精度。

      【讨论】:

        【解决方案5】:

        浮点数使用指数形式编码,类似于m * b ^ e,即根本不像整数。你问的问题在fixed point numbers 的上下文中是有意义的。有许多 fixed point arithmetic libraries 可用。

        关于浮点运算:小数位数取决于表示和数字系统。例如,有周期数 (0.33333) 在十进制中没有有限表示,但在二进制中有一个,反之亦然。

        另外值得一提的是,直到某一点的浮点数确实有大于一的差异,即value + 1 产生value,因为value + 1 不能使用m * b ^ e 编码,其中@987654330 @、be 的长度是固定的。小于 1 的值也会发生同样的情况,即所有可能的代码点的距离都不相同。

        因此,n 数字的精度与定点数字不同,因为并非每个具有 n 十进制数字的数字都具有 IEEE 编码。

        您应该阅读一份几乎是强制性的文档,其中解释了浮点数: What every computer scientist should know about floating point arithmetic.

        【讨论】:

        • +1 用于提及“每个计算机科学家都应该了解的浮点运算知识”。然而,值得注意的是,每一个数都有一个有限的二进制分数表示,也有一个有限的十进制表示。问题只是从十进制到二进制。
        【解决方案6】:

        查看Float.intBitsToFloatDouble.longBitsToDouble,它们可以解释位如何对应于浮点数。特别是,普通float 的位看起来像

         s * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW
        

        其中 A...W 是 23 位 -- 0 和 1 -- 表示二进制中的小数 -- s 是 +/- 1,分别由 0 或 1 表示,exp 是有符号的 8 位整数。

        【讨论】:

          猜你喜欢
          • 2015-03-18
          • 1970-01-01
          • 1970-01-01
          • 2018-02-23
          • 2011-01-24
          • 1970-01-01
          • 2015-05-17
          • 2015-02-20
          • 2011-07-12
          相关资源
          最近更新 更多