0

キャッチがあります!

IEEE 754単精度 (32 ビット) 浮動小数点数が 2 つの連続する 16 ビット整数に格納されています。

私が使用しているプロセッサには、浮動小数点演算や float データ型がありません! 私がやりたいことは、浮動小数点値を 16 ビットの符号付き整数に変換することです。プロセッサには、標準の整数演算とビット操作 (マスキング、シフトなど) があります。

ただし、32 ビットの浮動小数点から 16 ビットの整数に変換する際に、精度をいくらか下げる必要があります。整数には、問題の値の範囲に基づいた暗黙の倍率も必要です。

わかりやすくするための簡単な例を次に示します。float の範囲が0.00~であるとし10.00ます。この場合、整数の範囲を0 to 1000. 100 の暗黙のスケーリング係数に注意してください。この場合、整数の暗黙のスケーリングは 100 です。

IEEE 754には 1 つの符号ビット、指数用の 8 ビット (127 バイアス)、および仮数用の 23 ビットが含まれていることを知っています。

フロートの構成部分から値を再構築する式は次のとおりです。

float 値 = (-1)^Sign_bit * (1+仮数) * 2^(指数-127)。

私が見ることができる主な問題は、16 ビットの符号付き整数 (-32768 から +32767 の範囲) を操作し、オーバーフローまたはアンダーフローを回避することです。

4

1 に答える 1

0

スケーリングを使用して、32 ビット浮動小数点数を 16 ビット整数に変換します。ただし、指定した例では、2 進数ではなく 10 進数のスケーリングを使用しています。浮動小数点ユニットのないシステムで 2 進ドメインで作業を続けたいのか、実際に数値を 10 進表現に変換したいのか、私にはわかりません。

ここで、あなたの課題は、浮動小数点命令にアクセスできないことだと思います。プログラミング言語を指定していないので、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 の分数を使用して数値を表現したい場合は、 の値3を指定する必要がありますscaling。すべての数値は で乗算されます2^3 = 8。たとえば、0.125 = 1/8 は 1 に変換され、0.25 = 2/8 は 2 に変換されます。

コードは、丸め、NaN、オーバーフローなどのより複雑なものを処理しませんが、出発点として使用できますか?

于 2012-02-22T14:31:25.383 に答える