0

セットビットのcharとindexを受け取り、そのビットを含む1の文字列を分離する関数を考え出す必要があります。

すなわち

char isolate(unsigned char arg, int i);

例えば:

Isolate(221,2)は28を返します(11011101 >>> 00011100)

Isolate(221,6)は192(11011101 >>> 1100000)を返します

ルックアップテーブルは、〜256 * 8 = 2048エントリを必要とするため、扱いにくいソリューションのようです。

インデックスの左右にある個々のビットを調べることを考えています。

char isolate(char arg, int i)
{
   char result=0;
   char mask = 1<<i;
   for(char mask = 1<<i; arg & mask != 0; mask>>=1)
      result |= mask;
   for(char mask = 1<<i; arg & mask != 0; mask<<=1)
      result |= mask;
   return result;
}

しかし、それも少し醜いようです。どうすればこれよりもうまくいくことができますか?

4

2 に答える 2

3

それは面白い操作です。あなたが書いたコードはそれをかなりうまく表現しているので、それがいかに醜いかについて詳しく説明していただけませんか?

私が見ることができる詳細:それがiビット数を表すことを考えると、より広いタイプであることにはargまったく意味がありません。i条件で書くことに意味はありません!= 0。マスクを使用するすべての場所でマスクを再宣言したり、2回続けて初期化したりすることはおそらく望ましくありません。

実際の拡散ビットマスクに関しては、今のところ、より表現力豊かで、よりクリーンで、効率的な方法は考えられません。

于 2013-03-24T22:00:18.897 に答える
0

警告:これはテストされておらず、関連性もありません*が、興味深いかもしれません。

1の右端の実行を分離するのは、次のように簡単です:(x ^ (x & ((x|(x-1))+1))以下の説明)ので、それを使って作業しましょう。

最初x|(x-1)に右端の1を右に塗りつぶし、1を追加すると、1の右端の実行を含むすべてのビットが0になり、withxを使用すると、右端の1の実行が削除され、最後に、xoringを使用してx、右端の1の実行を残します。

次に、探している範囲が右端にあることを確認する必要があります。これは単純なビット計算にはあまり適していませんが、先行ゼロのカウント(clz)がある場合は、それほど難しくありません。

int shift = 32 - clz(~x & ((1 << i) - 1));  //replace 32 with word size
x = (x >> shift) << shift;

((1 << i) - 1)探している実行の右端が含まれる可能性のある部分のマスクを作成し(終了を見逃す可能性もありますが、それで問題ありません)、inclz右側にある最初のゼロを探し、次にシフトは、見たくないビットを削除します。ix

1の右端の実行を分離するための最初の式をその結果に適用して、実行された場所の実行を取得しますiiいくつかの実行にある方がよいか、物事が横向きになります(より正確には、の最初の実行が返されます)i)より高いインデックスで始まる1

*:この質問では、これは実際には重要ではありません。2KBのテーブルは、使用可能なメモリの量が少ない場合を除いて、不器用なソリューションではありません。その場合でも、入力が非常に短いため、ループはそれほど悪くありません。

于 2013-03-24T23:40:11.827 に答える