1

私は次の機能を持っています

int sign(int x) {

  int sign = (x >> 31);
  sign = sign | 1;
  return sign;

}

以下を希望します。

  • 負の数の場合は -1 を返します (最初の行)
  • 正数の場合は 1 を返します (2 行目)
  • ゼロの場合は 0 を返す

この最後の項目に行き詰まっています。x がゼロの場合、ビット単位の演算子のみを使用してゼロを返すにはどうすればよいですか?

4

3 に答える 3

2

素敵な小さなパズル。32 ビット整数があるとします。

int sign( int x )
{
   // if any bit is on, all bits are on. else zero.
   int lowBit = x;
   lowBit |= lowBit >> 16;
   lowBit |= lowBit >> 8;
   lowBit |= lowBit >> 4;
   lowBit |= lowBit >> 2;
   lowBit |= lowBit >> 1;
   lowBit &= 1;

   int signBit = x & 0x80000000;
   signBit |= signBit >> 16;
   signBit |= signBit >> 8;
   signBit |= signBit >> 4;
   signBit |= signBit >> 2;
   signBit |= signBit >> 1;
   signBit &= 0xFFFFFFFE;

   return signBit | lowBit;
}

これがどのように機能するかです。4ビットの数字で説明しますが、説明は一般化します。ビット パターンの 3 つのカテゴリからマッピングを作成する必要があります。

0000    -> 0000
0xxx    -> 0001
1yyy    -> 1111

ここで、x は 000 以外の任意の値、yyy は任意の値です。

したがって、最初に、レジスタ内のいずれかのビットが 1 の場合は 1 であり、それ以外の場合は 0 であるビットが必要です。そのため、いずれかのビットがハイの場合はすべてのビットがハイになるようにレジスタを「スミア」し、そのビットを結果のロー ビットの値として保持します。

次に、符号ビットを「塗りつぶします」。最後に、それらを一緒に「or」します。

読者のための演習: 32 ビットの int があるが、64 ビットのレジスタがある場合、操作の数を半分に削減できます。

更新: 常に改善できます (未テスト):

int sign( int x )
{
   int lowBit = !!x;  // double ! operator, wtf? yes...

   int signBit = x & 0x80000000;
   signBit |= signBit >> 16;
   signBit |= signBit >> 8;
   signBit |= signBit >> 4;
   signBit |= signBit >> 2;
   signBit |= signBit >> 1;
   signBit &= 0xFFFFFFFE;

   return signBit | lowBit;
}
于 2013-04-23T16:07:02.753 に答える
0

これを使って

int sign(int x) {

  int sign = (x >> 31);
  sign = sign | (~(1<<((x|(x>>5)|(x>>10)|(x>>15)|(x>>20)|(x>>25)|(x>>30))&0x1F))&0x1);
  return sign;

}

アイデアは、カウントで左シフト1することです。x

したがってx==0、最初のビットが保持される場合1

その場合x!=0、最初のビットは次のように変更されます0

そして、sign = sign | (~(First bit))

それは同等です

sign = sign | (~(1<<x) & 0x1);

1ただし、シフトをxで左に移動する場合は注意が必要です。これxは、型フォーマットのサイズ (32) に対して >= になる可能性があり、xが負になる可能性があり、どちらの場合も未定義の動作になるためです。

上記の問題を回避するために、32 ビット ( x) を 7 つのブロックに分割し、各ブロックには 5 ビットが含まれますが、最後のブロックには 2 ビットが含まれます|

y=(bloc1|bloc2|bloc3|bloc4|bloc5|bloc6|bloc7) 

もしそうx!= 0ならy!=0

もしそうx==0ならy==0

y( )の最初の 5 ビットのみを取得する必要があります&0x1F。ここで、それは否定的でyはなく、y<32

そして、でシフトする代わりに、でシフトして、未定義の動作を回避xできますy

于 2013-04-23T17:12:44.970 に答える
0

これも使えます。それは私の前の答えと同じ論理を持っています

int sign(int x) {
  int y = x;
  y |= y >> 16;
  y |= y >> 8;
  y |= y >> 4;
  y &= 0xF;

  int sign = (x >> 31);
  sign = sign | (~(1<<y) & 0x1);
  return sign;
}
于 2013-04-23T18:51:26.380 に答える