如何以2个字节保存浮点数?

是的我知道IEEE-754半精度标准,是的,我知道在该领域所做的工作。 简单地说,我试图在2个字节中保存一个简单的浮点数(如52.11.25 )。

我已尝试过Java和C#中的一些实现,但它们通过解码不同的数字来破坏输入值。 你输入32.1 ,编码解码后得到32.0985

有没有什么方法可以在不破坏输入值的情况下以16位存储浮点数?

非常感谢。

您可以在BCD中存储三位数字,并将剩余的四位用于小数点位置:

 52.1 = 521 * 10 ^ -1 => 0x1521 1.25 = 125 * 10 ^ -2 => 0x2125 

这将为您提供从0.0000000000000001到999的范围。您当然可以为小数点添加偏移量,以获得例如范围0.0000000001到999000000。


用于小数点放置的四位的简单实现,其余用于值。 没有任何错误检查,并没有彻底检查。 (使用!=比较双精度时,可能会出现某些值的精度问题。)

 public static short Encode(double value) { int cnt = 0; while (value != Math.Floor(value)) { value *= 10.0; cnt++; } return (short)((cnt << 12) + (int)value); } public static double Decode(short value) { int cnt = value >> 12; double result = value & 0xfff; while (cnt > 0) { result /= 10.0; cnt--; } return result; } 

例:

 Console.WriteLine(Encode(52.1)); Console.WriteLine(Decode(4617)); 

输出:

 4617 52.1 

C#没有内置function,但您可以尝试定点方法。

例8,8定点(逗号前8,后8):

 float value = 123.45; ushort fixedIntValue = (ushort)(value * 256); 

这样,数字存储如下:XXXXXXXX,XXXXXXXX

你可以使用这个再次检索浮点数:

 float value = fixedIntValue / 256f; 

你确定你需要这样的微优化,而不仅仅是使用floatdouble

通过存储short并理解,例如,它除以100来得到实际数字,你会更好吗? (例如,52.1和1.25的示例可以存储为5210和125)我认为这可能是最适合您的解决方案。

如果您使用的是实际浮点数,则可以将解码后的数字转换为x有效数字(从您的示例中为3),这通常会让您回到相同的数字(注意是的,这是故意模糊的 – 你不能保证获得原件,除非你存储原件)。

问题是您无法在任何二进制浮点类型中精确表示32.1

在单精度中,最接近的可表示值是32.099998。 半精度,显然是32.0985。

您可以考虑使用十进制浮点类型,但此解决方案并非半精度唯一。

有4,278,190,080个32位浮点值,不包括NaN和无穷大。 两个字节中的16位有65,536个值。 显然,不可能以两个字节唯一地编码所有浮点值。

你想编码哪些?

即使对于符号和指数的单个值(例如,所有浮点值从4到8,不包括8),也有8,388,608个浮点值,因此您甚至无法对两个字节中的那些进行编码。

您必须将自己限制为要编码的一小部分值。 完成后,人们可能会对如何编码它们提出建议。 你想要解决的实际问题是什么?

从您的示例中,您要存储3位数和小数点。 您可以简单地将11个符号的“字母”编码为4位代码,并以2个字节存储4 x 4位。