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

时间:2012-05-02 13:35:54

标签: c# binary floating-point ieee-754 numerical

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

我在JavaC#中尝试了一些实现,但它们通过解码不同的数字来破坏输入值。您输入32.1并在编码解码后得到32.0985

有没有办法在不破坏输入值的情况下只用16位存储浮点数?

非常感谢。

6 个答案:

答案 0 :(得分:6)

C#没有内置功能,但您可以尝试使用定点方法。

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

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

这样,数字就像这样存储: XXXXXXXX,XXXXXXXX

您可以使用以下方法再次检索浮点数:

float value = fixedIntValue / 256f;

答案 1 :(得分:6)

您可以在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

答案 2 :(得分:5)

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

通过存储short并了解例如将其除以100以获得实际数字,您会获得更好的服务吗? (例如,你的52.1和1.25的例子可以存储为5210和125)我认为这可能是你的最佳解决方案。

如果您使用的是实际浮点数,则可以将解码后的数字取整并将其四舍五入为有效数字x(从您的示例中为3),这通常会让您返回与您开始时相同的数字(请注意,是的,这是故意模糊的 - 除非您存储原件,否则无法保证获得原件。)

答案 3 :(得分:3)

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

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

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

答案 4 :(得分:2)

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

你想编码哪些?

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

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

答案 5 :(得分:1)

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