如何在浮点运算中舍入结果?

时间:2018-03-09 10:44:13

标签: c floating-point

我编写的代码简单地总结了n个数字的列表,用浮点运算来练习,我不明白这个:

我正在使用float,这意味着我有7位数的精度,因此,如果我执行操作10002 * 10002 = 100040004,数据类型float的结果将是100040000.000000,因为我丢失了超过7位的任何数字(程序仍然知道指数,如here}所示。

如果此程序中的输入是

3
10000
10001
10002

但是,你会看到,当这个程序计算30003 * 30003 = 900180009时,我们有30003 * 30003 = 900180032.000000

我理解这32是因为我正在使用float,我的目标不是让程序更精确,而是理解为什么会这样。为什么900180032.000000而不是900180000.000000?为什么这个十进制噪声(32)出现在30003 * 30003而不出现在10002 * 10002中,即使数字的大小相同?谢谢你的时间。

#include <stdio.h>
#include <math.h>
#define MAX_SIZE 200


int main() 
{
int numbers[MAX_SIZE]; 
int i, N;
float sum=0;
float sumb=0;
float sumc=0;

printf("introduce n" );
scanf("%d", &N);

printf("write %d numbers:\n", N);
for(i=0; i<N; i++)
{
    scanf("%d", &numbers[i]);
}

int r=0;

while (r<N){
    sum=sum+numbers[r];
    sumb=sumb+(numbers[r]*numbers[r]); 
    printf("sum is %f\n",sum);
    printf("sumb is %f\n",sumb);
    r++;
}
sumc=(sum*sum);
printf("sumc is %f\n",sumc);
}

2 个答案:

答案 0 :(得分:3)

如下所述,将10,002乘以10,002的计算结果必须是8的倍数,并且由于数字的大小和位数,计算的乘以30,003乘以30,003的结果必须是64的倍数。可以代表他们。虽然您的问题询问“十进制噪音”,但此处不涉及十进制数字。结果完全是由于四舍五入到2的幂的倍数。 (您的C实现似乎使用通用的IEEE 754格式进行二进制浮点。)

当您将10,002乘以10,002时,计算结果必须是8的倍数。我将在下面解释原因。数学结果为100,040,004。最接近的八的倍数是100,040,000和100,040,008。它们与确切的结果相差甚远,用于打破关系的规则选择偶数倍(100,040,000是8倍12,505,000,偶数,而100,040,008是8倍12,505,001,奇数)。

许多C实现对float使用IEEE 754 32位基本二进制浮点。在此格式中,数字表示为整数 M 乘以2 e 的幂。整数 M 的大小必须小于2 24 。指数 e 可以是-149到104.这些限制来自用于表示整数和指数的位数。

因此,对于某些 M ,此格式的所有float值都具有值 M •2 e em>和一些 e 。格式中没有小数位,只是一个整数乘以2的幂。

考虑数字100,040,004。我们可以使用的最大 M 是16,777,215(2 24 -1)。这还不够大,我们可以将100,040,004写为 M •2 0 。所以我们必须增加指数。即使有2 2 ,我们得到的最大值是16,777,215•2 2 = 67,108,860。所以我们必须使用2 3 。这就是为什么计算结果必须是8的倍数,在这种情况下。

因此,要在float中生成10,002•10,002的结果,计算机将使用12,505,000•2 3 ,即100,040,000。

在30,003•30,003中,结果必须是64的倍数。确切的结果是900,180,009。 2 5 是不够的,因为16,777,215•2 5 是536,870,880。所以我们需要2 6 ,即64.两个最接近的64的倍数是900,179,968和900,180,032。在这种情况下,后者更接近(23离开41离开),因此选择它。

(虽然我已经将格式描述为2的幂的整数倍,但它也可以描述为二进制数字,在小数点之前有一个二进制数字,在它之后有23个二进制数字,指数范围经过调整以补偿这些在数学上是等价的.IEEE 754标准使用后面的描述。教科书可能使用前面的描述,因为它使得分析一些数字属性更容易。)

答案 1 :(得分:2)

浮点运算以二进制形式完成,而不是十进制。

Floats实际上有24个二进制位的精度,其中1个是符号位,其中23个称为有效位。这将转换为大约 7精度的十进制数字。

您正在查看的数字 900180032 ,已经是9位数字,因此最后两位数字( 32 )可能有误。像算术这样的舍入是以二进制形式完成的,只有当你把事情分解为二进制时才能看到舍入差异的原因。

900180032 = 110101101001111010100001 000000

900180000 = 1101011010011110101000001 00000

如果从这些数字的第一个1到最后一个计数(我以粗体显示的部分),那就是存储数字所需的有效位数。 900180032仅存储23个有效位,而900180000需要24个有效位,这使得900180000不可能存储,因为浮点只有23个有效位。 900180032是浮点数可以存储的正确答案900180009的最接近的数字。

在另一个例子中

100040000 = 101111101100111110101 000000

100040004 = 1011111011001111101010001 00

正确答案,100040004有25个有效位,对浮点数来说太多了。具有23个或更少有效位的最接近的数字是10004000,其仅具有21个有效位。

有关浮点运算的更多信息,请尝试http://steve.hollasch.net/cgindex/coding/ieeefloat.html