IEEE浮点数表示法
1. 浮点数的存储结构
计算机中的所有数据都是以二进制的形式存储。
float
类型是32位(4字节),其中:符号位(1位):0表示正数,1表示负数。
指数位(8位):使用偏移量127(即指数实际值+127)表示。
尾数位(23位):即尾数的二进制表示。
具体存储格式(从高位到低位):
符号位 | 指数位 (8位) | 尾数位 (23位)
2. 浮点数转换过程
无小数的浮点数转换: 例如,浮点数
12345.0f
的转换过程:将整数部分转换为二进制。
将小数点向左移动,直到最高位是1,并计算对应的指数。
删除最高位的1(规范化)。
处理尾数,补充为23位。
计算最终的指数,并加上偏移量127。
带小数的浮点数转换: 例如,
123.456f
的转换:整数部分直接转换为二进制。
小数部分需要按二进制方法逐位求和,例如
0.57826
转为二进制小数。如果尾数超过23位,进行截断,导致精度丢失。
3. 浮点数精度问题
精度丢失:由于浮点数的尾数长度限制(最多23位),某些数(如
0.45
)无法精确表示。例如,0.45
转为二进制时,精度丢失无法完全表示,导致浮点数运算时的精度问题。二进制与十进制转换误差:像
0.45
这样的十进制小数转换成二进制时,必须截断尾数或近似表示,导致精度误差。
4. 小数的二进制表示
二进制小数(例如
0.100101011
)的位阶依次是1/(2^1)
,1/(2^2)
,1/(2^3)
等。例如,
0.456
无法准确转化为二进制数,导致精度丢失。
5. 常见的浮点数表示实例
例如,
123.456f
的最终二进制表示为:
符号位:0
指数位:10000101
尾数位:11101101110100101111001
转换后的16进制表示为42 F6 E9 79
,反转后为79 E9 F6 42
。
对于
0.0f
,其二进制表示为00 00 00 00
。
6. C++代码解析浮点数结构
文章最后给出了一个C++函数
DecodeFloat
,可以分析并输出浮点数的结构。该函数将浮点数的二进制、符号、指数和尾数进行解析,并计算最终的浮点数值。
代码示例:
void DecodeFloat( BYTE pByte[4] )
{
printf( "原始(十进制):%d %d %d %d\n" , (int)pByte[0],
(int)pByte[1], (int)pByte[2], (int)pByte[3] );
printf( "翻转(十进制):%d %d %d %d\n" , (int)pByte[3],
(int)pByte[2], (int)pByte[1], (int)pByte[0] );
bitset<32> bitAll( *(ULONG*)pByte );
string strBinary = bitAll.to_string<char, char_traits<char>, allocator<char> >();
strBinary.insert( 9, " " );
strBinary.insert( 1, " " );
cout << "二进制:" << strBinary.c_str() << endl;
cout << "符号:" << ( bitAll[31] ? "-" : "+" ) << endl;
bitset<32> bitTemp;
bitTemp = bitAll;
bitTemp <<= 1;
LONG ulExponent = 0;
for ( int i = 0; i < 8; i++ )
{
ulExponent |= ( bitTemp[ 31 - i ] << ( 7 - i ) );
}
ulExponent -= 127;
cout << "指数(十进制):" << ulExponent << endl;
bitTemp = bitAll;
bitTemp <<= 9;
float fMantissa = 1.0f;
for ( int i = 0; i < 23; i++ )
{
bool b = bitTemp[ 31 - i ];
fMantissa += ( (float)bitTemp[ 31 - i ] / (float)( 2 << i ) );
}
cout << "尾数(十进制):" << fMantissa << endl;
float fPow;
if ( ulExponent >= 0 )
{
fPow = (float)( 2 << ( ulExponent - 1 ) );
}
else
{
fPow = 1.0f / (float)( 2 << ( -1 - ulExponent ) );
}
cout << "运算结果:" << fMantissa * fPow << endl;
}
License:
CC BY 4.0