7

を (配列に格納される) に変換するintegerにはどうすればよいですか。入力 int の範囲は 1 ~ 65535 です。精度は本当に問題ではありません。half precision floatunsigned char[2]

を に変換するために似たようなことを16bit intしていますが、 C++ データ型unsigned char[2]がないことは理解しています。half precision float以下の例:

int16_t position16int = (int16_t)data;
memcpy(&dataArray, &position16int, 2);
4

4 に答える 4

5

必要な情報はすべてウィキペディアにあります。

実装例:

#include <stdio.h>

unsigned int2hfloat(int x)
{
  unsigned sign = x < 0;
  unsigned absx = ((unsigned)x ^ -sign) + sign; // safe abs(x)
  unsigned tmp = absx, manbits = 0;
  int exp = 0, truncated = 0;

  // calculate the number of bits needed for the mantissa
  while (tmp)
  {
    tmp >>= 1;
    manbits++;
  }

  // half-precision floats have 11 bits in the mantissa.
  // truncate the excess or insert the lacking 0s until there are 11.
  if (manbits)
  {
    exp = 10; // exp bias because 1.0 is at bit position 10
    while (manbits > 11)
    {
      truncated |= absx & 1;
      absx >>= 1;
      manbits--;
      exp++;
    }
    while (manbits < 11)
    {
      absx <<= 1;
      manbits++;
      exp--;
    }
  }

  if (exp + truncated > 15)
  {
    // absx was too big, force it to +/- infinity
    exp = 31; // special infinity value
    absx = 0;
  }
  else if (manbits)
  {
    // normal case, absx > 0
    exp += 15; // bias the exponent
  }

  return (sign << 15) | ((unsigned)exp << 10) | (absx & ((1u<<10)-1));
}

int main(void)
{
  printf(" 0: 0x%04X\n", int2hfloat(0));
  printf("-1: 0x%04X\n", int2hfloat(-1));
  printf("+1: 0x%04X\n", int2hfloat(+1));
  printf("-2: 0x%04X\n", int2hfloat(-2));
  printf("+2: 0x%04X\n", int2hfloat(+2));
  printf("-3: 0x%04X\n", int2hfloat(-3));
  printf("+3: 0x%04X\n", int2hfloat(+3));
  printf("-2047: 0x%04X\n", int2hfloat(-2047));
  printf("+2047: 0x%04X\n", int2hfloat(+2047));
  printf("-2048: 0x%04X\n", int2hfloat(-2048));
  printf("+2048: 0x%04X\n", int2hfloat(+2048));
  printf("-2049: 0x%04X\n", int2hfloat(-2049)); // first inexact integer
  printf("+2049: 0x%04X\n", int2hfloat(+2049));
  printf("-2050: 0x%04X\n", int2hfloat(-2050));
  printf("+2050: 0x%04X\n", int2hfloat(+2050));
  printf("-32752: 0x%04X\n", int2hfloat(-32752));
  printf("+32752: 0x%04X\n", int2hfloat(+32752));
  printf("-32768: 0x%04X\n", int2hfloat(-32768));
  printf("+32768: 0x%04X\n", int2hfloat(+32768));
  printf("-65504: 0x%04X\n", int2hfloat(-65504)); // legal maximum
  printf("+65504: 0x%04X\n", int2hfloat(+65504));
  printf("-65505: 0x%04X\n", int2hfloat(-65505)); // infinity from here on
  printf("+65505: 0x%04X\n", int2hfloat(+65505));
  printf("-65535: 0x%04X\n", int2hfloat(-65535));
  printf("+65535: 0x%04X\n", int2hfloat(+65535));
  return 0;
}

出力 ( ideone ):

 0: 0x0000
-1: 0xBC00
+1: 0x3C00
-2: 0xC000
+2: 0x4000
-3: 0xC200
+3: 0x4200
-2047: 0xE7FF
+2047: 0x67FF
-2048: 0xE800
+2048: 0x6800
-2049: 0xE800
+2049: 0x6800
-2050: 0xE801
+2050: 0x6801
-32752: 0xF7FF
+32752: 0x77FF
-32768: 0xF800
+32768: 0x7800
-65504: 0xFBFF
+65504: 0x7BFF
-65505: 0xFC00
+65505: 0x7C00
-65535: 0xFC00
+65535: 0x7C00
于 2012-10-10T12:15:15.417 に答える
2

32 ビット浮動小数点を 16 ビット浮動小数点に変換する方法について質問しました。

Float32 ~ Float16

そのため、int を float に非常に簡単に変換し、上記の質問を使用して 16 ビット float を作成できます。これはおそらく int から直接 16 ビット float に移行するよりもはるかに簡単です。事実上、32 ビット浮動小数点数に変換することで、ほとんどのハードワークが完了し、あとは数ビットをシフトするだけで済みます。

編集:Alexeyの優れた答えを見ると、ハードウェアintからfloatへの変換を使用してからビットシフトする方が、彼の方法よりもかなり高速になる可能性が高いと思います。両方の方法をプロファイリングして比較する価値があるかもしれません。

于 2012-10-10T11:04:28.573 に答える
0

サポートされているハードウェアをターゲットにしている場合は、組み込み関数を使用できます。

https://software.intel.com/en-us/articles/performance-benefits-of-half-precision-floats https://software.intel.com/sites/products/documentation/doclib/iss/2013/compiler /cpp-lin/GUID-7679FF37-257B-4F90-8668-5B3AA62587AD.htm

于 2014-12-02T22:34:50.300 に答える
0

@kbok の質問のコメントに続いて、この回答の最初の部分を使用してハーフフロートを取得し、次に配列を取得しました。

uint16_t position16float = float_to_half_branch(data);
memcpy(&dataArray, &position16float, 2);
于 2012-10-10T11:35:55.937 に答える