本文主要介绍如何将32位的IBM单精度浮点数转化成 32位的IEEE单精度浮点数。
1、32位浮点数存储在四个字节中,首先要确定字节序。
什么为字节序呢?字节序是指多字节数据在计算机内存中存储或者网络传输中个字节的存放顺序。
常见的字节序有:大字节序 和 小字节序。
大字节序:数据的高位字节存放在内存的低地址字节中。
小字节序:数据的低位字节存放在内存的低地址字节中。(我们常用的intel系列是小字节序)。
将0x0A0B0C0D 写入到内存中,大小字节序的区别如下图:
2、IBM 和 IEEE 浮点数的结构如下:S 代表符号、E 代表指数部分、F 代表位数部分。
浮点数的表示如下:
IBM 浮点数结构:
IEEE浮点数结构:
3、IBM 和 IEEE 浮点数的一些区别:
尾数的有效范围:
IEEE浮点数,尾数的最小值为 1/(2^23);
IBM浮点数,尾数的最小值为1/16,而不是1/(2^24);
特定概念值(如下图):
4、IBM转IEEE转换思路:
1)、提取符号、指数部分、尾数部分。
2)、判断指数部分的值,转换特定概念值。
3)、指数部分转换,IEEE阶码= IBM阶码 * 4 -130。
4)、尾数规格化,因为IEEE浮点数能表示的最小数是1/16,所以规格化过程最多左移三次。
5)、处理转化后指数的移出问题。
6)、转化后的符号。指数、尾数的组装。
5、代码如下:
private static float IBMtoIEEE(byte[] bb)
{
uint fraction;
int exponent;
int sign;
uint ui;
根据情况看是否进行字节转换
//System.Array.Reverse(bb);
// @ 标识符号位
// # 标识阶数位
// * 标识尾数位
//IBM浮点数: SEEEEEEE MMMMMMMM MMMMMMMM MMMMMMMM Value = (-1)^s * M * 16^(E-64)
//IEEE浮点数:SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM Value = (-1)^s * (1 + M) * 2^(E-127)
fraction = System. BitConverter.ToUInt32(bb, 0);
sign = ( int)(fraction >> 31); // 获取符号位;
fraction <<= 1; // 左移移出符号位,右侧填0;
exponent = ( int)(fraction >> 25); // 获取阶数;
fraction <<= 7; //移出符号位 和 阶数 剩余的部分:尾数部分;
/*
* 如果尾数部分为0,则说明该数是特定值:0或者无穷。
* 当指数=127,说明当前数是无穷大; 对应的IEEE无穷大时,指数为255
* 当指数=0,说明当前数为0;对应的IEEE为0时,指数为255
* 当0<指数<127,根据公式 (-1)^s * M * 16^(E-64) ,M为0,则最后结果是0;对应的IEEE为0时,指数为255
*/
if (fraction == 0)
{
if (exponent != 127)
exponent = 0;
else
exponent = 255;
goto done;
}
// 将IBM 浮点数的阶码转化成 IEEE 的阶码:(exp - 64) * 4 + 127 - 1 == exp * 4 - 256 + 126 == (exp << 2) - 130
//IEEE阶码= IBM阶码 * 4 -130
exponent = (exponent << 2) - 130;
// 将尾数规格化,因为浮点数能表示的最小数是1/16,所以规格化过程最多左移三次。
while (fraction < 0x80000000)
{
--exponent;
fraction <<= 1;
}
if (exponent <= 0) //下限溢出,指数不能小于零 0<=E(ieee)<=254
{
//if (exponent < -24)
//{
// // complete underflow - return properly signed zero
// fraction = 0;
//}
//else
//{
// // partial underflow - return denormalized number
// fraction >>= -exponent;
//}
exponent = 0;
fraction = 0;
}
else if (exponent >= 255) //上限溢出:指数不能大于255;表示无穷大;
{
fraction = 0;
exponent = 255;
}
else //IEEE尾码 = IBM尾码 * 2 -1;相当于左移一位
{
fraction <<= 1;
}
done:
ui = ( uint)((exponent << 23) | (sign << 31));
ui = ui | (fraction >> 9);
bb = System. BitConverter.GetBytes(ui);
return System.BitConverter .ToSingle(bb, 0);
}
IEEE浮点数 转 IBM 浮点数请参考:点击打开链接