繁体   English   中英

对于IEEE float,C ++`digits10`是6,但是第一个不可表示的整数已经有8位数?

[英]C++ `digits10` is 6 for IEEE float, but the first non-representable integer already has 8 digits?

C ++的std::numeric_limits<float>::digits10在cppref中描述如下:

std::numeric_limits<T>::digits10的值是可以由类型T表示而没有更改的基数为10的数字,也就是说,具有此多个十进制数字的任何数字都可以转换为类型的值T并返回小数形式,不会因舍入或溢出而改变。

C表兄弟FLT_DIG存在类似的描述。

给出的值是:

 float FLT_DIG /* 6 for IEEE float */ 

但是这里显示的是,在32位IEEE浮点类型中,高达16,777,216 (2 24 )的所有整数都可以精确表示。 如果我能算,这个数字有8位,所以对于价值digits10实际上应该是7,现在不应该吗?

而是很明显,我误解了一些关于digits10这里,那么,这实际上告诉我吗?


实用性:

有人问我,如果我们能够从存储所有号码0.00 - 86,400.00正是在IEEE 32位浮点。

现在,我非常有信心我们可以在IEEE 32位浮点数中存储08,640,000所有数字,但这是否适用于向左移动2位数的相同“整数”范围?

(限制IEEE754 float答案)。

8.589973e98.589974e9都映射到8589973504 这是第7个有效数字被保留的断言的反例。

由于第6个有效数字上不存在这样的反例,因此std::numeric_limits<float>::digits10FLT_DIG为6。

实际上,整数可以精确地表示为2的24 幂。( 16,777,21616,777,217都映射到16,777,216 )。 这是因为float具有24位有效数

正如另一个答案和评论所确定的digits10涵盖了所有“指数范围”,即它必须保持1234567以及1.23456712345670000 - 这仅适用于6位数!

7位数的反例:

  • 8.589,973 e9 vs. 8.589,974 e9 (来自cppref示例)

有时候很容易找到反例。

#include <stdio.h>
#include <string.h>

int main(void) {
  int p6 = 1e6;
  int p7 = 1e7;
  for (int expo = 0; expo < 29; expo++) {
    for (int frac = p6; frac < p7; frac++) {
      char s[30];
      sprintf(s, "%d.%06de%+03d", frac / p6, frac % p6, expo);
      float f = atof(s);
      char t[30];
      sprintf(t, "%.6e", f);
      if (strcmp(s, t)) {
        printf("<%s> %.10e <%s>\n", s, f, t);
        break;
      }
    }
  }
  puts("Done");
}

产量

<8.589973e+09> 8.5899735040e+09 <8.589974e+09>
<8.796103e+12> 8.7961035080e+12 <8.796104e+12>
<9.007203e+15> 9.0072024760e+15 <9.007202e+15>
<9.223377e+18> 9.2233775344e+18 <9.223378e+18>
<9.444738e+21> 9.4447374693e+21 <9.444737e+21>
<9.671414e+24> 9.6714134744e+24 <9.671413e+24>
<9.903522e+27> 9.9035214949e+27 <9.903521e+27>
<1.000000e+28> 9.9999994421e+27 <9.999999e+27>  This is an interesting one

另一个角度来看:

考虑在每对2的幂之间,像IEEE二进制float编码线性分布的2 23个值。


示例:介于2 0和2 1或1.0和2.0之间,

float值之间的差异是1.0 / 2 23或10.192e-06。

以文本形式“1.dddddd”(7位数字)编写,数字相差1.000e-06。

因此,对于十进制文本编号的每一步,大约有10.2 float
编码这7位数字没有问题。
在此范围内,编码8位数也没有问题。


示例:介于2 23和2 24或8,388,608.0和16,777,216.0之间。

float值之间的差异是2 23/2 23或1.0。

以文本形式“8or9.ddddd * 10 6 ”(7位有效数字)写的低端附近的数字相差1.0。

编码这7位数字没有问题。


示例:介于2 33和2 34或8,589,934,592.0和17,179,869,184.0之间,

之间的差float值是2 33/2 23或1,024.0。

以文本形式“8or9.ddddd * 10 9 ”(7位有效数字)写的低端附近的数字相差1,000.0。

现在我们遇到了问题。 从8,589,934,592.0开始,接下来文本形式的1024个数字只有1000个不同的float编码。


d.dddddd * 10 expo形式的7位数字太多,无法使用float进行唯一编码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM