0

有一个问题!

我有一个IEEE 754单精度(32 位)浮点数,存储在两个连续的 16 位整数中。

我使用的处理器没有浮点数学或浮点数据类型!我想要做的是将浮点值转换为 16 位有符号整数。处理器具有标准整数数学和位操作(屏蔽、移位等)。

我除了在从 32 位浮点数到 16 位整数时需要失去一些精度。该整数还需要一些基于所讨论的值范围的隐含比例因子。

这是一个简单的例子,可以让事情更清楚。假设浮点数的范围为0.00to 10.00。在这种情况下,我希望整数的范围从0 to 1000. 注意隐含的比例因子 100。在这种情况下,整数的隐含比例为 100。

我知道IEEE 754包含 1 个符号位,8 位用于指数(具有 127 偏差)和 23 位用于尾数。

我知道从浮点数的组成部分重建值的方程是:

浮点值 = (-1)^Sign_bit * (1+尾数) * 2^(Exponent-127)。

我可以看到的主要问题是使用 16 位有符号整数(范围为 -32768 到 +32767)并避免任何溢出或下溢。

4

1 回答 1

0

您想通过缩放将 32 位浮点数转换为 16 位整数。但是,您给出的示例使用十进制缩放而不是二进制。我不确定您是否想在没有浮点单元的系统上继续在二进制域中工作,或者您是否真的想转换为数字的十进制表示。

在这里,我假设您的挑战是您无法访问浮点指令。你还没有指定编程语言,所以我决定用 C# 编写一些东西。该语言易于使用,但可能不是最适合摆弄的语言。你可能会发现用 C 或 C++ 来实现它更容易、更有效。

因为我将继续使用二进制表示,所以比例不能是像 10 或 100(10 的整数幂)这样的数字,而是必须是 2 的整数幂。下面是一个采用 IEEE 754 binary32 浮点数的类点数分开。

class Ieee754Binary32 {

  public Ieee754Binary32(Single value) {
    using (var memoryStream = new MemoryStream()) {
      var binaryWriter = new BinaryWriter(memoryStream);
      binaryWriter.Write(value);
      memoryStream.Seek(0, SeekOrigin.Begin);
      var binaryReader = new BinaryReader(memoryStream);
      var bits = binaryReader.ReadInt32();
      Fraction = bits & 0x7FFFFF;
      Exponent = ((bits >> 23) & 0xFF) - 127;
      Sign = (bits & 80000000) == 1 ? -1 : 1;
    }
  }

  public Int32 Fraction { get; private set; }

  public Int32 Exponent { get; private set; }

  public Int32 Sign { get; private set; }

  public Int16 ToScaledInt16(Int32 scaling) {
    if (Exponent == -127 && Fraction == 0)
      return 0;
    var mantissa = 0x8000 | (Fraction >> 8);
    var unscaledInt32 = Exponent >= 0 ? mantissa << Exponent : mantissa >> -Exponent;
    var scaledInt16 = unscaledInt32 >> (15 - scaling);
    return (Int16) (Sign*scaledInt16);
  }

}

该方法ToScaledInt16是您想要使用的。如果您想使用 8 的分数表示数字,您应该提供 的3scaling。所有数字都将乘以2^3 = 8,例如 0.125 = 1/8 转换为 1,0.25 = 2/8 转换为 2 等。

该代码不处理更复杂的东西,如舍入、NaN 或溢出,但也许您可以将其用作起点?

于 2012-02-22T14:31:25.383 回答