我遇到了一些float
我不了解的C类型的行为,希望可以对此进行解释。使用float.h
I中定义的宏可以确定数据类型可以存储在给定硬件上的最大值/最小值。但是,当执行不应超过这些限制的计算时,我发现成功的类型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
虽然与编译icc
的sumval_f = 67108864.0
,因此最终的比为2.0,而不是*。请注意,float
总和是不正确的,而double
总和是正确的。
据我所知,FLT_MAX
建议的总和应适合float
,但似乎稳定在全部价值的八分之一或一半。
是否存在编译器特定的替代,可使用查找的值float.h
?为什么double
需要正确找到此数组的总和?
*有趣的是,在for循环中包含if语句,该语句打印数组的值,导致该值与gcc输出匹配,即正确总和的八分之一,而不是一半。
这里的问题不是值的范围,而是精度。
假设32位IEEE754 float
,则此数据类型的最大精度为24位。这意味着并非所有大于16777216的整数都可以精确表示。
因此,当总和达到16777216时,将其加1超出了数据类型可以存储的精度,因此该数字不会增加。
(大概)64位double
具有53位精度。这足以容纳所有整数值,直到134217728的总和,因此可以为您提供准确的结果。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句