如何计算尾数位数?

时间:2016-03-05 12:35:20

标签: c++ c

我想计算float和double中的尾数位数。 我知道这些数字应该是23和52,但我必须在我的程序中计算它。

2 个答案:

答案 0 :(得分:5)

您可以使用标题<cfloat>

中定义的常量

例如,请参阅FLT_MANT_DIG。

答案 1 :(得分:3)

尾数位数存在歧义:它可能是

  • 表示浮点值所需的位数。
  • 存储在浮点表示中的位数。

通常,以IEEE浮点格式存储的尾数不包括对所有常规非零数字暗示的初始1。因此,表示中的位数比真正的位数少一个。

您可以通过不同方式为二进制浮点格式计算此数字:

  • 某些系统定义了清单包含FLT_MANT_BITSDBL_MANT_BITSLDBL_MANT_BITS。该值是尾数位的真实数。
  • 您可以从涉及FLT_EPSILON中定义的<float.h>的直接计算中导出位数:FLT_EPSILON是最小的浮点值,使1.0f + FLT_EPSILON与{1.0f不同1}}。真尾数是1 - log(FLT_EPSILON) / log(2)。相同的公式可用于其他浮点格式。
  • 您可以使用循环计算值,如下面的代码所示。

这是一个测试工具:

#include <float.h>
#include <math.h>
#include <stdio.h>

int main(void) {
    int n;
    float f = 1.0;
    for (n = 0; 1.0f + f != 1.0f; n++) {
        f /= 2;
    }
#ifdef FLT_MANT_BITS
    printf("#define FLT_MANT_BITS       %d\n", FLT_MANT_BITS);
#endif
#ifdef FLT_EPSILON
    printf("1 - log(FLT_EPSILON)/log(2) =  %g\n", 1 - log(FLT_EPSILON) / log(2));
#endif
    printf("Mantissa bits for float: %d\n", n);
    double d = 1.0;
    for (n = 0; 1.0 + d != 1.0; n++) {
        d /= 2;
    }
#ifdef DBL_MANT_BITS
    printf("#define DBL_MANT_BITS       %d\n", DBL_MANT_BITS);
#endif
#ifdef DBL_EPSILON
    printf("1 - log(DBL_EPSILON)/log(2) =  %g\n", 1 - log(DBL_EPSILON) / log(2));
#endif
    printf("Mantissa bits for double: %d\n", n);
    long double ld = 1.0;
    for (n = 0; 1.0 + ld != 1.0; n++) {
        ld /= 2;
    }
#ifdef LDBL_MANT_BITS
    printf("#define LDBL_MANT_BITS      %d\n", LDBL_MANT_BITS);
#endif
#ifdef LDBL_EPSILON
    printf("1 - log(LDBL_EPSILON)/log(2) = %g\n", 1 - log(LDBL_EPSILON) / log(2));
#endif
    printf("Mantissa bits for long double: %d\n", n);
    return 0;
}

我的笔记本电脑输出:

1 - log(FLT_EPSILON)/log(2) =  24
Mantissa bits for float:       24
1 - log(DBL_EPSILON)/log(2) =  53
Mantissa bits for double:      53
1 - log(LDBL_EPSILON)/log(2) = 64
Mantissa bits for long double: 64