在 C# 中将两个字节转换为 IEEE-11073 16 位 SFLOAT
Converting two bytes to an IEEE-11073 16-bit SFLOAT in C#
我需要根据 IEEE-11073 将两字节数组转换为 SFloat 格式。
我该怎么做?
我在这里回答我的问题。
public float ToSFloat(byte[] value)
{
if (value.Length != 2)
throw new ArgumentException();
byte b0 = value[0];
byte b1 = value[1];
var mantissa = unsignedToSigned(ToInt(b0) + ((ToInt(b1) & 0x0F) << 8), 12);
var exponent = unsignedToSigned(ToInt(b1) >> 4, 4);
return (float)(mantissa * Math.Pow(10, exponent));
}
public int ToInt(byte value)
{
return value & 0xFF;
}
private int unsignedToSigned(int unsigned, int size)
{
if ((unsigned & (1 << size-1)) != 0)
{
unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1)));
}
return unsigned;
}
粗略地基于 C implementation by Signove on GitHub 我在 C# 中创建了这个函数:
Dictionary<Int32, Single> reservedValues = new Dictionary<Int32, Single> {
{ 0x07FE, Single.PositiveInfinity },
{ 0x07FF, Single.NaN },
{ 0x0800, Single.NaN },
{ 0x0801, Single.NaN },
{ 0x0802, Single.NegativeInfinity }
};
Single Ieee11073ToSingle(Byte[] bytes) {
var ieee11073 = (UInt16) (bytes[0] + 0x100*bytes[1]);
var mantissa = ieee11073 & 0x0FFF;
if (reservedValues.ContainsKey(mantissa))
return reservedValues[mantissa];
if (mantissa >= 0x0800)
mantissa = -(0x1000 - mantissa);
var exponent = ieee11073 >> 12;
if (exponent >= 0x08)
exponent = -(0x10 - exponent);
var magnitude = Math.Pow(10d, exponent);
return (Single) (mantissa*magnitude);
}
此函数假定字节为小端格式。如果不是,则必须在函数的第一行交换 bytes[0]
和 bytes[1]
。或者甚至更好地从函数中删除第一行并更改函数参数以接受 UInt16
(IEEE 11073 值),然后让调用者决定如何从输入中提取此值。
我强烈建议您测试此代码,因为我没有任何测试值来验证转换的正确性。
public float ToSFloat(byte[] value)
{
if (value.Length != 2)
throw new ArgumentException();
byte b0 = value[0];
byte b1 = value[1];
var mantissa = unsignedToSigned(ToInt(b0) + ((ToInt(b1) & 0x0F) << 8), 12);
var exponent = unsignedToSigned(ToInt(b1) >> 4, 4);
return (float)(mantissa * Math.Pow(10, exponent));
}
public int ToInt(byte value)
{
return value & 0xFF;
}
private int unsignedToSigned(int unsigned, int size)
{
if ((unsigned & (1 << size-1)) != 0)
{
unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1)));
}
return unsigned;
}
我需要根据 IEEE-11073 将两字节数组转换为 SFloat 格式。
我该怎么做?
我在这里回答我的问题。
public float ToSFloat(byte[] value)
{
if (value.Length != 2)
throw new ArgumentException();
byte b0 = value[0];
byte b1 = value[1];
var mantissa = unsignedToSigned(ToInt(b0) + ((ToInt(b1) & 0x0F) << 8), 12);
var exponent = unsignedToSigned(ToInt(b1) >> 4, 4);
return (float)(mantissa * Math.Pow(10, exponent));
}
public int ToInt(byte value)
{
return value & 0xFF;
}
private int unsignedToSigned(int unsigned, int size)
{
if ((unsigned & (1 << size-1)) != 0)
{
unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1)));
}
return unsigned;
}
粗略地基于 C implementation by Signove on GitHub 我在 C# 中创建了这个函数:
Dictionary<Int32, Single> reservedValues = new Dictionary<Int32, Single> {
{ 0x07FE, Single.PositiveInfinity },
{ 0x07FF, Single.NaN },
{ 0x0800, Single.NaN },
{ 0x0801, Single.NaN },
{ 0x0802, Single.NegativeInfinity }
};
Single Ieee11073ToSingle(Byte[] bytes) {
var ieee11073 = (UInt16) (bytes[0] + 0x100*bytes[1]);
var mantissa = ieee11073 & 0x0FFF;
if (reservedValues.ContainsKey(mantissa))
return reservedValues[mantissa];
if (mantissa >= 0x0800)
mantissa = -(0x1000 - mantissa);
var exponent = ieee11073 >> 12;
if (exponent >= 0x08)
exponent = -(0x10 - exponent);
var magnitude = Math.Pow(10d, exponent);
return (Single) (mantissa*magnitude);
}
此函数假定字节为小端格式。如果不是,则必须在函数的第一行交换 bytes[0]
和 bytes[1]
。或者甚至更好地从函数中删除第一行并更改函数参数以接受 UInt16
(IEEE 11073 值),然后让调用者决定如何从输入中提取此值。
我强烈建议您测试此代码,因为我没有任何测试值来验证转换的正确性。
public float ToSFloat(byte[] value)
{
if (value.Length != 2)
throw new ArgumentException();
byte b0 = value[0];
byte b1 = value[1];
var mantissa = unsignedToSigned(ToInt(b0) + ((ToInt(b1) & 0x0F) << 8), 12);
var exponent = unsignedToSigned(ToInt(b1) >> 4, 4);
return (float)(mantissa * Math.Pow(10, exponent));
}
public int ToInt(byte value)
{
return value & 0xFF;
}
private int unsignedToSigned(int unsigned, int size)
{
if ((unsigned & (1 << size-1)) != 0)
{
unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1)));
}
return unsigned;
}