5

ビットマスクを使用して、複数の値を 1 つの変数に格納する一般的な方法があります。たとえば、ユーザーがアイテムに対する読み取り、書き込み、および実行の権限を持っている場合、それを 1 つの数字に変換するには、read = 4 (2^2), write = 2 (2^1), execute = 1 (2^0)これらを足し合わせて 7 を取得します。

私はこの手法をいくつかの Web アプリケーションで使用しています。通常、変数をフィールドに格納し、異なる値の数に応じて MEDIUMINT などの型を指定します。

私が興味を持っているのは、このように保存できる値の数に実際的な制限があるかどうかです? たとえば、数値が 64 を超えると、(64 ビット) 整数を使用できなくなります。この場合、あなたは何を使いますか?プログラム ロジックにどのような影響がありますか (つまり、ビットごとの比較を引き続き使用できますか)。

非常に大きな値のセットを取得し始めると、別の方法が最適なソリューションになることはわかっていますが、この方法の境界に興味があります。

4

7 に答える 7

3

頭のてっぺんから、バイト配列と配列内のビットオフセットを取り、ビット操作を使用して配列内の適切なビットを設定/取得できるset_bitand関数を作成します。get_bitこのようなもの(Cでは、うまくいけばアイデアが得られます):

// sets the n-th bit in |bytes|. num_bytes is the number of bytes in the array
// result is 0 on success, non-zero on failure (offset out-of-bounds)
int set_bit(char* bytes, unsigned long num_bytes, unsigned long offset)
{
  // make sure offset is valid
  if(offset < 0 || offset > (num_bytes<<3)-1) { return -1; }

  //set the right bit
  bytes[offset >> 3] |= (1 << (offset & 0x7));

  return 0; //success 
}

//gets the n-th bit in |bytes|. num_bytes is the number of bytes in the array
// returns (-1) on error, 0 if bit is "off", positive number if "on"
int get_bit(char* bytes, unsigned long num_bytes, unsigned long offset)
{
  // make sure offset is valid
  if(offset < 0 || offset > (num_bytes<<3)-1) { return -1; }

  //get the right bit
  return (bytes[offset >> 3] & (1 << (offset & 0x7));
}
于 2008-10-07T03:03:48.797 に答える
2

ビット マスクがマシン ワードの何倍も大きいファイル システム コードでビット マスクを使用しました。「ブール値の配列」のように考えてください。

(知りたい場合は、フラッシュメモリのジャーナリングマスク)

多くのコンパイラは、これを行う方法を知っています。OO コードを少し追加して、適切に動作する型を持たせると、コードがビットバンギングではなく、意図したように見え始めます。

私の2セント。

于 2008-10-07T02:50:53.597 に答える
1

古いスレッドですが、32 個の bigint フィールド (SQL Server は UInt32 をサポートしていません) にパックされた 1024 ビット配列として生成されることが多い、分子フィンガープリントなどの肥大化したビット マスクが必要な場合があることに言及する価値があります。テーブルが大きくなり始め、個別の関数呼び出しの遅さに気付くまで、ビット単位の操作は正常に機能します。T-SQL で 2 つのバイナリ オペランドを持つビット演算子が禁止されていなければ、バイナリ データ型は機能します。

于 2013-09-22T03:53:34.227 に答える
1

一部の言語 (perl はそうだと思いますが、確かではありません) は、文字列に対してビット単位の算術演算を許可します。有効範囲が大幅に広がります。( (strlen * 8bit chars ) の組み合わせ )

ただし、複数の /type/ データの重ね合わせに単一の値を使用することはありません。3 ビット int の基本的な r/w/x トリプレットは、スペース効率の理由ではなく、実用的な開発上の理由から、おそらく「実用的な」上限になります。

( PHP はこのシステムを使用してエラー メッセージを制御します。PHP の定数が常駐せず、手動で整数を生成する必要がある場合に値を定義する必要がある場合は、少しやり過ぎであることが既にわかっています。正直なところ、chmod が 'ugo+rwx' スタイルの構文をサポートしていない場合は、マジック ナンバーを思い出せないので、絶対に使いたくありません)

コードをデバッグするために定数テーブルをクラックして開かなければならない瞬間に、行き過ぎていることがわかります。

于 2008-10-07T03:04:15.113 に答える
1

64 ビット整数では、最大 2^64-1 の値を格納できます。64 は 2^6 にすぎません。はい、制限がありますが、64 個以上のフラグが必要な場合は、それらがすべて何をしていたかを知りたいと思います :)

潜在的に考える必要がある州はいくつありますか? 64 の潜在的な状態がある場合、それらが存在できる組み合わせの数は、64 ビット整数のフルサイズです。

128 個のフラグについて心配する必要がある場合は、ビット ベクトルのペアで十分です (2^64 * 2)。

追加: パールのプログラミングでは、整数で実装された長さ 10^7 のビット配列を使用することについての拡張された議論があります (使用される 800 個の数値を保持するため)。これは非常に高速で、その章で説明されているタスクに非常に適しています。

于 2008-10-07T02:50:53.783 に答える
0

たとえば、.NET は BitArray クラスの内部ストレージとして整数の配列を使用します。実際には、他の方法はありません。

そうは言っても、SQL では、すべての状態を格納するために複数の列が必要になります (または BLOBS を使用します)。

于 2008-10-07T02:57:47.827 に答える
0

この質問に SQL のタグを付けたので、データベースのドキュメントを参照して整数のサイズを確認する必要があると思います。次に、念のため、符号を 1 ビット減算します。

編集:あなたのコメントは、MySQL を使用していると言っています。MySQL 5.0 Numeric Typesのドキュメントには、NUMERIC の最大サイズは 64 または 65 桁であると記載されています。これは、64 桁で 212 ビットです。

選択した言語はこれらの数字を処理できる必要があるため、とにかく 64 ビット整数に制限される可能性があることに注意してください。

于 2008-10-07T03:06:38.807 に答える