如果我们运行此代码:
#include <iostream>
int main ()
{
using namespace std;
float a = 2.34E+22f;
float b = a+1.0f;
cout<<"a="<<a<<endl;
cout<<"b-a"<<b-a<<endl;
return 0;
}
然后结果将为0,因为浮点数只有6位有效数字。但是浮点数1.0试图添加到23位数字。那么,程序如何意识到数字1没有位置,算法是什么?
答案 0 :(得分:1)
基本原则是两个数字对齐,小数点位于同一位置。我使用10位数字使其更容易阅读:
a = 1.234E+10f;
b = a+1.0f;
计算+ 1.0f时,需要排列小数点:
1.234E+10f becomes 1234000000.0
1.0f becomes 1.0
+
= 1234000001.0
但是由于它的浮动,右边的1超出了有效范围,所以存储的数字将是1.234000E+10
- 除此之外的任何数字都会丢失,因为没有足够的数字。
[注意,如果在优化编译器上执行此操作,它仍可能显示1.0作为差异,因为浮点单元使用64位或80位内部表示,因此如果计算完成而不存储中间体得到一个变量(一个体面的编译器当然可以在这里实现)2.34E + 22f保证不适合64位浮点数,也可能不适用于80位浮点数。
答案 1 :(得分:1)
一步一步:
IEEE-754 32位二进制浮点格式:
sign 1 bit significand 23 bits exponent 8 bits
I)float a = 23400000000.f;
将23400000000.f
转换为float
:
23,400,000,000 = 101 0111 0010 1011 1111 1010 1010 0000 00002 = 1.01011100101011111110101010000000002 • 234.
但有效点只能在该点后存储23位。所以我们必须围绕:
1.01011100101011111110101 010000000002 • 234 ≈ 1.010111001010111111101012 • 234
所以,之后:
float a = 23400000000.f;
a
等于23,399,991,808。
II)float b = a + 1;
a = 101011100101011111110101000000000002. b = 101011100101011111110101000000000012 = 1.01011100101011111110101000000000012 • 234.
但是,有效点再次只能存储23个二进制数字。所以我们必须围绕:
1.01011100101011111110101 000000000012 • 234 ≈ 1.010111001010111111101012 • 234
所以,之后:
float b = a + 1;
b
等于23,399,991,808。
III)float c = b - a;
101011100101011111110101000000000002 - 101011100101011111110101000000000002 = 0
此值可以存储在float
中,而不会进行舍入。
所以,之后:
float c = b - a;
с
等于0.
答案 2 :(得分:0)
添加两个FP编号时,它们首先转换为相同的指数。十进制:
2.34000E+22 + 1.00000E0 = 2.34000E22 + 0.000000E+22
。在此步骤中,1.0将丢失以进行舍入。
二进制浮点的工作原理基本相同,只是E + 22被2 ^ 77取代。