2009-05-23 22:54:21| 分类: 编程技术 | 标签: |字号大中小 订阅
IEC 60870-5-4中对于定点数F16的定义如下:
F16:=F16[1..16]<-1..+1-2-15>
其最高位为符号位,第14~0为分别表示2的负1~负15次幂。当最高位为1而其后所有位均为0时表示-1。整个数据的表示范围为-1~1-2的负15次幂。可以用下面的函数直观地将该定点数转换为浮点数:
/// <summary>
/// F16定点数转换为浮点数
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static float F16ToFloat(byte[] data)
{
double result = 0f;
byte tmpByte = data[0];
for (int i = 0; i < 8; i++)
{
if (GetBit(tmpByte, i))
{
result += Math.Pow(2, i - 15);
}
}
tmpByte = data[1];
for (int i = 0; i < 7; i++)
{
if (GetBit(tmpByte, i))
{
result += Math.Pow(2, i - 7);
}
}
if (GetBit(tmpByte, 7)) result += -1;
return (float)result;
}
/// <summary>
/// 获取字节某一位的状态
/// </summary>
/// <param name="data">字节</param>
/// <param name="index">偏移</param>
/// <returns>位状态</returns>
public static bool GetBit(byte data, int index)
{
Debug.Assert(index >= 0 && index < 8);
byte tmpByte = (byte)(0x1 << index);
return (data & tmpByte) == tmpByte;
}
上述方法虽然可行,但由于进行了大量的运算,效率较低。经过恶补浮点数在内存中的表示方法,更主要的是学习了小数部分的表示方法,将上述方法改进如下:
/// <summary>
/// F16定点数转换为浮点数
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static float F16ToFloat(byte[] data)
{
Debug.Assert(data.Length == 2);
//提取符号位
bool sign = GetBit(data[1], 7);
//移除符号位
data[1] &= 0x7f;
UInt32 holder = (UInt32)BitConverter.ToUInt16(data, 0);
//浮点数的尾数部分在第0~22位,因此需要平移
holder = holder << 8;
holder = holder | (0x7f << 23);
float result = BitConverter.ToSingle(BitConverter.GetBytes(holder), 0);
//由于固定数的值在0~1之间,而浮点数的尾数在1~2之间,需要对其进行转换
//符号位
if (sign)
{
return result - 2;
}
else
{
return result - 1;
}
}
/// <summary>
/// 浮点数转换为F16
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static byte[] FloatToF16(float data)
{
bool sign = (data < 0);
if (sign)
{
data += 2;
}
else
{
data += 1;
}
UInt32 holder = BitConverter.ToUInt32(BitConverter.GetBytes(data),0);
holder = holder >> 8;
if (sign)
holder |= 0x8000;
else
holder &= 0x7fff;
byte[] result = new byte[2];
Array.Copy(BitConverter.GetBytes(holder), 0, result, 0, 2);
return result;
}
联系客服