了解可以在C中的浮点数中存储的最大值

用户名

我遇到了一些float我不了解的C类型的行为,希望可以对此进行解释。使用float.hI中定义的宏可以确定数据类型可以存储在给定硬件上的最大值/最小值。但是,当执行不应超过这些限制的计算时,我发现成功的类型float变量失败double以下是一个最小示例,该示例在我的计算机上编译。

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

int main(int argc, char **argv)
{
    int gridsize;
    long gridsize3;

    float *datagrid;

    float sumval_f;
    double sumval_d;

    long i;

    gridsize = 512;
    gridsize3 = (long)gridsize*gridsize*gridsize;

    datagrid = calloc(gridsize3, sizeof(float));
    if(datagrid == NULL)
    {
        free(datagrid);
        printf("Memory allocation failed\n");
        exit(0);
    }

    for(i=0; i<gridsize3; i++)
    {
        datagrid[i] += 1.0;
    }

    sumval_f = 0.0;
    sumval_d = 0.0;
    for(i=0; i<gridsize3; i++)
    {
        sumval_f += datagrid[i];
        sumval_d += (double)datagrid[i];
    }

    printf("\ngridsize3 = %e\n", (float)gridsize3);
    printf("FLT_MIN = %e\n", FLT_MIN);
    printf("FLT_MAX = %e\n", FLT_MAX);
    printf("DBL_MIN = %e\n", DBL_MIN);
    printf("DBL_MAX = %e\n", DBL_MAX);

    printf("\nfloat sum = %f\n", sumval_f);
    printf("double sum = %lf\n", sumval_d);
    printf("sumval_d/sumval_f = %f\n\n", sumval_d/(double)sumval_f);

    free(datagrid);
    return(0);
}

编译后gcc我发现输出:

gridsize3 = 1.342177e+08
FLT_MIN = 1.175494e-38
FLT_MAX = 3.402823e+38
DBL_MIN = 2.225074e-308
DBL_MAX = 1.797693e+308

float sum = 16777216.000000
double sum = 134217728.000000
sumval_d/sumval_f = 8.000000

虽然与编译iccsumval_f = 67108864.0,因此最终的比为2.0,而不是*。请注意,float总和是不正确的,而double总和是正确的。

据我所知,FLT_MAX建议的总和应适合float,但似乎稳定在全部价值的八分之一或一半。

是否存在编译器特定的替代,可使用查找的值float.h为什么double需要正确找到此数组的总和?

*有趣的是,在for循环中包含if语句,该语句打印数组的值,导致该值与gcc输出匹配,即正确总和的八分之一,而不是一半。

dbush

这里的问题不是值的范围,而是精度

假设32位IEEE754 float,则此数据类型的最大精度为24位。这意味着并非所有大于16777216的整数都可以精确表示。

因此,当总和达到16777216时,将其加1超出了数据类型可以存储的精度,因此该数字不会增加。

(大概)64位double具有53位精度。这足以容纳所有整数值,直到134217728的总和,因此可以为您提供准确的结果。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章