C中浮点数据类型的范围?

C中浮点数据类型的范围?,c,floating-point,ieee-754,C,Floating Point,Ieee 754,我正在读一本C语言的书,谈到浮点的范围,作者给出了表格: Type Smallest Positive Value Largest value Precision ==== ======================= ============= ========= float 1.17549 x 10^-38 3.40282 x 10^38 6 digits double 2.22507 x 10^-308

我正在读一本C语言的书,谈到浮点的范围,作者给出了表格:

Type     Smallest Positive Value  Largest value      Precision
====     =======================  =============      =========
float    1.17549 x 10^-38         3.40282 x 10^38    6 digits
double   2.22507 x 10^-308        1.79769 x 10^308   15 digits

我不知道列中最小正值和最大值的数字来自哪里。

这些数字来自标准,它定义了浮点数的标准表示形式。Wikipedia链接上的一篇文章:如何在知道符号、尾数和指数所用位数的情况下得出这些范围。

这是该类型指数部分大小的结果,例如IEEE 754。可以在float.h中使用FLT_MAX、FLT_MIN、DBL_MAX、DBL_MIN检查大小

32位浮点数有23+1位尾数和8位指数(-126到127),因此可以表示的最大数字是:

(1 + 1 / 2 + ... 1 / (2 ^ 23)) * (2 ^ 127) = 
(2 ^ 23 + 2 ^ 23 + .... 1) * (2 ^ (127 - 23)) = 
(2 ^ 24 - 1) * (2 ^ 104) ~= 3.4e38

正如dasblinkenlight已经回答的那样,这些数字来自于IEEE-754中浮点数的表示方式,Andreas有一个很好的数学分解

但是,请注意,浮点数的精度并非如表中所示的6或15位有效十进制数字,因为IEEE-754数字的精度取决于有效二进制数字的数量

  • float
    有24个有效的二进制数字-根据所表示的数字转换为精度为6-8位的十进制数字

  • double
    有53个有效的二进制数字,约为15个十进制数字


如果您感兴趣,请提供进一步的解释。

浮点数据类型的值来自总共32位,表示如下分配的数字:

1位:符号位

8位:指数p

23位:尾数

指数存储为
p+BIAS
,其中BIAS为127,尾数有23位,第24个隐藏位假定为1。此隐藏位是尾数的最高有效位(MSB),必须选择指数,使其为1

这意味着您可以表示的最小数字是
010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

最大值为
0111111111111111111
,尾数为2*(1-1/65536),指数为127,给出
(1-1/65536)*2^128=3.40277175E38

同样的原则适用于双精度,但位除外:

1位:符号位

11位:指数位

52位:尾数位

偏差:1023


因此,从技术上讲,这些限制来自IEEE-754标准,用于表示浮点数,以上是这些限制如何产生的

无穷大、NaN和次正常值

这些是迄今为止没有其他答案提及的重要警告

首先阅读IEEE 754和次正常数字的介绍:

然后,对于单精度浮点(32位):

  • IEEE 754指出,如果指数都是1(
    0xFF==255
    ),那么它代表NaN或无穷大

    这就是为什么最大的非无限数具有指数
    0xFE==254
    而不是
    0xFF

    然后随着偏差的增加,它变成:

    254 - 127 == 127
    
  • FLT_MIN
    是最小的正常值。但也有比正常小的!它们占据了
    -127
    指数槽

以下程序的所有断言都在Ubuntu 18.04 amd64上传递:

#include <assert.h>
#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

float float_from_bytes(
    uint32_t sign,
    uint32_t exponent,
    uint32_t fraction
) {
    uint32_t bytes;
    bytes = 0;
    bytes |= sign;
    bytes <<= 8;
    bytes |= exponent;
    bytes <<= 23;
    bytes |= fraction;
    return *(float*)&bytes;
}

int main(void) {
    /* All 1 exponent and non-0 fraction means NaN.
     * There are of course many possible representations,
     * and some have special semantics such as signalling vs not.
     */
    assert(isnan(float_from_bytes(0, 0xFF, 1)));
    assert(isnan(NAN));
    printf("nan                  = %e\n", NAN);

    /* All 1 exponent and 0 fraction means infinity. */
    assert(INFINITY == float_from_bytes(0, 0xFF, 0));
    assert(isinf(INFINITY));
    printf("infinity             = %e\n", INFINITY);

    /* ANSI C defines FLT_MAX as the largest non-infinite number. */
    assert(FLT_MAX == 0x1.FFFFFEp127f);
    /* Not 0xFF because that is infinite. */
    assert(FLT_MAX == float_from_bytes(0, 0xFE, 0x7FFFFF));
    assert(!isinf(FLT_MAX));
    assert(FLT_MAX < INFINITY);
    printf("largest non infinite = %e\n", FLT_MAX);

    /* ANSI C defines FLT_MIN as the smallest non-subnormal number. */
    assert(FLT_MIN == 0x1.0p-126f);
    assert(FLT_MIN == float_from_bytes(0, 1, 0));
    assert(isnormal(FLT_MIN));
    printf("smallest normal      = %e\n", FLT_MIN);

    /* The smallest non-zero subnormal number. */
    float smallest_subnormal = float_from_bytes(0, 0, 1);
    assert(smallest_subnormal == 0x0.000002p-126f);
    assert(0.0f < smallest_subnormal);
    assert(!isnormal(smallest_subnormal));
    printf("smallest subnormal   = %e\n", smallest_subnormal);

    return EXIT_SUCCESS;
}
输出:

nan                  = nan
infinity             = inf
largest non infinite = 3.402823e+38
smallest normal      = 1.175494e-38
smallest subnormal   = 1.401298e-45

它们来自浮点类型的范围。正确但无用的答案是“IEEE 754”。你的意思是为什么这些值的限制?IEEE 754是C标准要求的吗?@foo,IEEE 754格式是常见的,有些书往往不区分实现特征和所需语言,有些人在书中清楚地显示了一个或多个语言不需要的常见实现特征时往往不注意。这些宏是C吗标准宏?我问的原因是INT_MAX和INT_MIN在限制中可用。h.那些似乎在限制中不可用。hw值得一提的是,这是最小的正常值,有更小的次正常值:这里我解释为什么奇怪的
-126
127
范围只包含253个数字,而不是预期的255个(一个用于无穷大,另一个用于次正常值):
nan                  = nan
infinity             = inf
largest non infinite = 3.402823e+38
smallest normal      = 1.175494e-38
smallest subnormal   = 1.401298e-45