为什么浮点数的有效数字是7或6

时间:2018-04-22 01:03:10

标签: c floating-point precision

我在维基百科log 224 = 7.22中看到了这一点。

我不知道为什么我们应该计算2 ^ 24以及为什么我们应该使用log10 ......我真的需要你的帮助。

3 个答案:

答案 0 :(得分:4)

  

为什么浮点数的有效数字是7或6(?)

考虑使用Pigeonhole principle的一些想法:

  1. binary32 float可以编码大约2 32 不同的数字完全。即使我们将自己限制在-10 38 ... +10 38 。任何时间代码都有0.1f等文本值,它会被编码到附近的float,这可能不是完全相同的文本值。问题是:我们可以编码多少位数并仍保持独特float
  2. 对于各种2的幂范围,2 23 (8,388,608)值通常线性编码。
  3. 在[1.0 ... 2.0]范围内,2 23 (8,388,608)值线性编码。
  4. 在[2 33 或8,589,934,592 ... 2 34 或17,179,869,184)范围内,同样,2 23 (8,388,608)值为线性编码:1024.0彼此分开。在子范围[9,000,000,000和10,000,000,000]中,大约有976,562个不同的值。
  5. 把它放在一起......

    1. 作为文本,范围[1.000_000 ... 2.000_000),使用1个引导数字和6个跟踪数字,有1,000,000个不同的值。每#3,在相同的范围内,存在8,388,608个不同的float,允许每个文本值映射到不同的float在此范围内,我们可以使用7位

    2. 作为文本,范围[9,000,000 * 10 3 和10,000,000 * 10 3 ),使用1个引导数字和6个跟踪数字,有1,000,000个不同值。每#4,在相同的范围内,有不到1,000,000个不同的float值。因此,一些十进制文本值将转换为相同的float在此范围内,我们可以使用6位数字,而不是7位进行特殊转换。

    3. 典型float更糟糕的情况是 6位有效数字。要查找您的 float的限制:

      #include <float.h>
      printf("FLT_DIG = %d\n", FLT_DIG);  // this commonly prints 6
      
        

      ......不知道为什么我们应该计算2 ^ 24以及我们为什么要采用log10

      2 ^ 24是一个泛化,与普通float及其24位二进制精度一样,对应于具有7.22的幻想十进制系统...数字。我们使用 log10 二进制 float十进制文本进行比较。

      2 24 == 10 7.22 ...

      然而,我们应该采取2 24 。让我们看看如何从C11dr§5.2.4.2.2中定义FLT_DIG 11:

        

      小数位数, q ,这样任何带有 q 十进制数字的浮点数都可以用 p <舍入为浮点数/ em> radix b 数字并再次返回而不更改 q 十进制数字,

           

      p log 10 b .............如果b是10的幂/>   ⎣( p - 1)log 10 b ⎦..否则

      注意“log 10 2 24 ”与“24 log 10 2”相同。

      作为float,值在2的幂之间以线性分布,如#2,3,4所示。

      作为 text ,值在10的幂之间以线性分布,如7个有效数字值[1.000000 ... 9.999999] * 10 some_exponent

      这两组的转变发生在不同的值。 1,2,4,8,16,32 ...与1,10,100,......在确定最坏情况时,我们从24位中减去1以解决错位。

      ⎣( p - 1)log 10 b ⎦ - &gt; floor((24 − 1) log10(2)) - &gt; floor(6.923...) - &gt; 6。

      如果我们的float使用了基数10,100或1000,而不是非常常见的2,则这两组的转换发生在相同的值,我们不会减去一个。

答案 1 :(得分:2)

IEEE 754 single-precision float有一个24位的尾数。这意味着它有24个二进制位的精确度。

但我们可能有兴趣知道它有多少十进制数字的精确度。

计算它的一种方法是考虑有多少24位二进制数。答案当然是2 24 。所以这些二进制数从0到16777215。

那是多少位十进制数?好吧,log10给出了小数位数。 log10(2 24 )是7.2,或者略多于7位小数。

看一下:16777215有8位数,但前导数字只有1,所以实际上只有7位数。

(当然这并不意味着我们只能代表0到16777215之间的数字!这意味着我们可以代表0到16777215 的数字。但我们也有代表玩我们可以将0到1677721.5之间的数字或多或少精确地表示到小数点后的一个地方,数字从0到167772.15或多或少精确到两个小数点等等。我们可以表示0到167772150之间的数字,或者0到0 1677721500,但逐渐不那么精确 - 总是有~7位数的精度,这意味着我们开始将低位数字的精度丢失到小数点的 left 。)

另一种方法是注意log10(2)约为0.3。这意味着1位对应于约0.3个十进制数字。所以24位对应24×0.3 = 7.2。

(实际上,IEEE 754单精度浮点只显式地存储了23位,而不是24位。但是那里有一个隐含的前导1位,所以我们确实得到了24位的效果。)

答案 2 :(得分:0)

让我们开始小一些。使用10位(或10个基数2位数),您可以将数字0表示为1023.因此,对于某些值,您最多可以表示4位数,但对于大多数其他值(1000以下的数字),最多可以表示3位数。

要找出一堆基数为2位(位)可以表示多少个10(十进制)数,你可以使用最大可表示值的log10(),即log10(2 ^ 10) = log10(2)* 10 = 3.01 ....

以上意味着您可以表示所有3位数或更小值 - 以及几个4位数值。嗯,这很容易验证:0-999最多有3位数,1000-1023有4位数。

现在需要24位。在24位中,您可以存储log10(2 ^ 24)= 24 * log(2)基数为10的数字。但由于顶部位始终相同,实际上只能存储log10(2 ^ 23)= log10(8388608)= 6.92。这意味着您可以代表大多数7位数字,但不是全部。您可以忠实代表的一些数字只能有6位数。

事实上,事实有点复杂,因为指数也起作用,而且许多可能更大的值中的一些也可以表示,因此6.92可能不是确切的值。但它很接近,可以很好地作为一个经验法则,这就是为什么他们说单精度可以代表6到7位数。