您必须缩放数字以使它们具有相同的指数。然后添加尾数字段,并在必要时对结果进行标准化。
哦,是的,如果它们是不同的符号,您只需调用减法函数即可:-)
让我们用十进制做一个例子,因为它更容易理解。我们进一步假设它们仅存储小数点右侧的八位数字(并且数字在 0 和 1 之间)。
将两个数字相加:
sign exponent mantissa value
1 42 18453284 + 0.18453284 x 10^42
1 38 17654321 + 0.17654321 x 10^38
将这些数字缩放到最高指数给出了可以添加尾数字段的内容:
sign exponent mantissa value
1 42 18453284 + 0.18453284 x 10^42
1 42 1765 + 0.00001765 x 10^42
= == ========
1 42 18455049 + 0.18455049 x 10^42
那里有你的电话号码。这也说明了如何因移动而损失准确性。例如,IEEE754 单精度浮点数将具有:
1e38 + 1e-38 = 1e38
例如:
#include <stdio.h>
int main (void) {
float f1 = 1e38;
float f2 = 1e-38;
float f3 = f1 + f2;
float f4 = f1 - f3;
printf ("%.50f\n", f4);
return 0;
}
就溢出发生的情况而言,这是我提到的标准化的一部分。让我们添加99999.9999
to 99999.9993
。由于它们已经具有相同的指数,因此无需缩放,因此我们只需添加:
sign exponent mantissa value
1 5 99999999 + 0.99999999 x 10^5
1 5 99999993 + 0.99999999 x 10^5
= == ========
1 5 199999992 ???
您可以在这里看到我们有进位情况,因此我们无法将该进位放入数字中,因为限制为八位数字。然后我们要做的就是将数字向右移动,以便我们can插入进位。由于该移位实际上是除以十,因此我们必须增加指数来抵消这一点。
So:
sign exponent mantissa value
1 5 199999992 ???
becomes:
sign exponent mantissa value
1 6 19999999 + 0.19999999 x 10^6
实际上,这不仅仅是简单的右移,因为您需要四舍五入到最接近的数字。如果移出的数字是五或更多,则需要在左边的数字上加一。这就是我选择的原因99999.9993
作为第二个数字。如果我添加了99999.9999
就其本身而言,我最终会得到:
sign exponent mantissa value
1 5 199999998 ???
在右移时,会触发相当多的向左进位:
sign exponent mantissa value
1 6 20000000 + 0.2 x 10^6