C中求解数学表达式时的浮点问题



我有一个用c语言解决数学问题的函数。

double task1_double() {
double a = 1000;
double b = 0.0001;
double result = (pow((a + b), 2) - (pow(a, 2) + 2 * a * b))/(pow(b, 2));
return result; }
float task1_float() {
float a = 1000;
float b = 0.0001f;
float result = (powf((a + b), 2) - (powf(a, 2) + 2 * a * b))/(powf(b, 2));
return result; }

当我使用double数据类型时,它返回1.001172,而使用float数据类型时,结果是6250000.000000。

谁能解释一下为什么会这样?提前感谢

你的分子正好是

1000000.20000001 - 1000000.2 = 0.00000001

但是当你相减两个几乎相等的大数时,结果中的相对舍入误差可能会放大。这就是你所看到的。这是由于float的数字大约有7位十进制的精度,而double的数字大约有16位十进制的精度。

让我们一步一步来做:

exact            float        double
x = pow((a + b), 2)        1000000.20000001 1000000.25   1000000.200000009965
y = pow(a, 2) + 2 * a * b  1000000.2        1000000.1875 1000000.199999999953
x - y                      0.00000001       0.0625       0.000000010011717677

对于两个数字相对于它们的大小而言如此小的差异,您通常会得到等于0.0的float结果。但在这种情况下,1000000.20000001和1000000.2恰好位于舍入边界的两侧,导致前者四舍五入,后者四舍五入。所以他们的差异是6个数量级。

通过输出中间结果可以发现,这是由于float

的精度损失造成的。

#include <stdio.h>
#include <math.h>
double task1_double() {
double a = 1000;
double b = 0.0001;
double s1, s2, s3;
s1 = pow((a + b), 2);
s2 = pow(a, 2) + 2 * a * b;
s3 = pow(b, 2);
double result = (pow((a + b), 2) - (pow(a, 2) + 2 * a * b)) / (pow(b, 2));
printf("_double : %lf - %lf = %.15lfn", s1, s2, s1 - s2);
printf("_double : (%lf - %lf) / %.10lf = %lfn", s1, s2, s3, result);
return result;
}
float task1_float() {
float a = 1000;
float b = 0.0001f;
float s1, s2, s3;
s1 = powf((a + b), 2);
s2 = powf(a, 2) + 2 * a * b;
s3 = powf(b, 2);
float result = (powf((a + b), 2) - (powf(a, 2) + 2 * a * b)) / (powf(b, 2));
printf("_float : %lf - %lf = %.15lfn", s1, s2, s1 - s2);
printf("_float : (%lf - %lf) / %.10lf = %lfn", s1, s2, s3, result);
return result;
}
int main()
{
printf("%.10lfn%.10lfn", task1_double(), task1_float());
return 0;
}

输出:

_float : 1000000.250000 - 1000000.187500 = 0.062500000000000
_float : (1000000.250000 - 1000000.187500) / 0.0000000100 = 6250000.500000
_double : 1000000.200000 - 1000000.200000 = 0.000000010011718
_double : (1000000.200000 - 1000000.200000) / 0.0000000100 = 1.001172
1.0011717677
6250000.5000000000

可以看出:浮点数操作后,会出现一个小误差,但除以b的小值会使误差放大很多倍

相关内容

  • 没有找到相关文章

最新更新