Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 计算数组c+的平均值+;_C++_Precision - Fatal编程技术网

C++ 计算数组c+的平均值+;

C++ 计算数组c+的平均值+;,c++,precision,C++,Precision,当我试图用两种方法计算数组的平均值时,遇到了一个问题。代码如下: float sum1, sum2, tmp, mean1, mean2; double sum1_double, sum2_double, tmp_double; int i, j; int Nt=29040000; //array size int piecesize=32; int Npiece=Nt/piecesize; float* img; float* d_img; double* img_double; img_d

当我试图用两种方法计算数组的平均值时,遇到了一个问题。代码如下:

float sum1, sum2, tmp, mean1, mean2;
double sum1_double, sum2_double, tmp_double;
int i, j;
int Nt=29040000;  //array size
int piecesize=32;
int Npiece=Nt/piecesize;
float* img;
float* d_img;
double* img_double;
img_double = (double*)calloc(Nt, sizeof(double));
cudaHostAlloc((void**)&img, sizeof(float)*Nt, cudaHostAllocDefault);
cudaMalloc((void**)&d_img, sizeof(float)*Nt);
...
//Some calculation is done in GPU and the results are stored in d_img;
...    
cudaMemcpy(img, d_img, Nt*sizeof(float), cudaMemcpyDeviceToHost);
for (i=0;i<Nt;i++) img_double[i]=(double)img[i];

//Method 1
sum1=0;
for (i=0;i<Nt;i++) 
{ sum1 += img[i]; }

sum1_double=0;
for (i=0;i<Nt;i++) 
{ sum1_double += img_double[i]; }

//Method 2
sum2=0;
for (i=0;i<Npiece;i++)
{   tmp=0; 
      for (j=0;j<piecesize;j++)
        { tmp += img[i*piecesize+j];}
    sum2 += tmp;
}

sum2_double=0;
for (i=0;i<Npiece;i++)
{   tmp_double=0; 
      for (j=0;j<piecesize;j++)
        { tmp_double += img_double[i*piecesize+j];}
    sum2_double += tmp_double;
}

mean1=sum1/(float)Nt;
mean2=sum2/(float)Nt;
mean1_double=sum1_double/(double)Nt;
mean2_double=sum2_double/(double)Nt;

cout<<setprecision(15)<<mean1<<endl;
cout<<setprecision(15)<<mean2<<endl;
cout<<setprecision(15)<<mean1_double<<endl;
cout<<setprecision(15)<<mean2_double<<endl;
从两种方法(平均值1=129.6,平均值2=132.2)获得的结果显著不同。我可以知道为什么吗


提前多谢

原因是浮点运算不精确。当您累加整数时,当abs(value)大于224时(我假设IEEE-754是32位的),float就变得不精确了。例如,float无法精确存储16777217(它将变为16777216或16777218,具体取决于舍入模式)

假设您的第二次计算更精确,因为由于单独的
tmp
累积,精度损失更少

sum1
sum2
tmp
变量更改为
long-long-int
,希望两种计算结果相同


注意:我假设您的
img
存储整数数据。如果它存储浮点数,那么就没有简单的方法可以完美地解决这个问题。一种方法是对
sum1
sum2
tmp
使用
double
而不是
float
。差别会存在,但会小得多。还有一些技术可以比简单的求和更精确地累加
float
s。原因是浮点运算不精确。当您累加整数时,当abs(value)大于224时(我假设IEEE-754是32位的),float就变得不精确了。例如,float无法精确存储16777217(它将变为16777216或16777218,具体取决于舍入模式)

假设您的第二次计算更精确,因为由于单独的
tmp
累积,精度损失更少

sum1
sum2
tmp
变量更改为
long-long-int
,希望两种计算结果相同



注意:我假设您的
img
存储整数数据。如果它存储浮点数,那么就没有简单的方法可以完美地解决这个问题。一种方法是对
sum1
sum2
tmp
使用
double
而不是
float
。差别会存在,但会小得多。还有一些技术可以比简单的求和更精确地累加
float
s。比如。

为什么不打印总数。@6502很好。还有更好的用户名。我想念我的Atari。“//数组数据存储在img中”显示代码,而不是注释。我想用for循环简单填充
29040000
元素就是一个很好的例子。还有一个简单的测试用例,如果您将它们都设置为相同的值,那么您可以验证至少该测试用例的平均值是否正确。也许这对您有用:为什么不打印总和。@6502很好。还有更好的用户名。我想念我的Atari。“//数组数据存储在img中”显示代码,而不是注释。我想用for循环简单填充
29040000
元素就是一个很好的例子。还有一个简单的测试用例,如果你将它们都设置为相同的值,那么你可以验证平均值至少对该测试用例是正确的。也许这对你有用:谢谢你的回答。img中的数据是
float
类型。如何将其更改为
long-long-int
。您可能需要双精度then@geza谢谢你的信息。我试过使用
double
类型。正如您在更新后的帖子中看到的,使用
double
从方法1和方法2获得的结果是相同的。@drescherjm我已经使用double更新了我的帖子。结果似乎更好。谢谢。@JianGao:一般情况下,它们是不一样的。即使如此,它们目前也可能不完全相同(更精确地打印数字,比如20个重要的数字)。但是可能差别太小了,所以对你来说不是问题。谢谢你的回答。img中的数据是
float
类型。如何将其更改为
long-long-int
。您可能需要双精度then@geza谢谢你的信息。我试过使用
double
类型。正如您在更新后的帖子中看到的,使用
double
从方法1和方法2获得的结果是相同的。@drescherjm我已经使用double更新了我的帖子。结果似乎更好。谢谢。@JianGao:一般情况下,它们是不一样的。即使如此,它们目前也可能不完全相同(更精确地打印数字,比如20个重要的数字)。但也许差别很小,所以对你来说不是问题。
132.221862792969
129.565872192383
129.565938340543
129.565938340543