web-dev-qa-db-ja.com

実際のプロジェクトでビットシフトを使用する必要がありましたか?

実際のプログラミングプロジェクトで bit shift を使用する必要がありましたか?ほとんどの(すべてではないにしても)高レベル言語にはシフト演算子がありますが、実際に使用する必要があるのはいつですか?

78
Philip Morton

ハードウェアで浮動小数点をサポートしていないシステム用のコードをまだ書いています。これらのシステムでは、ほぼすべての算術演算にビットシフトが必要です。

また、ハッシュを生成するにはシフトが必要です。多項式演算(CRC、リードソロモンコードが主流のアプリケーションです)またはシフトも使用します。

ただし、シフトは便利であり、作家の意図を正確に表現するため、シフトが使用されます。必要に応じて、すべてのビットシフトを乗算でエミュレートできますが、それは書くのが難しく、読みにくく、時には遅くなります。

コンパイラは、乗算をシフトに減らすことができる場合を検出します。

54

はい、私はそれらを何度も使用しました。ビットマスクが非常に一般的な組み込みハードウェアでは、ビットの調整が重要です。また、ゲームプログラミングでは、パフォーマンスのすべての最後のビットが必要な場合にも重要です。

編集:また、色深度の変更、RGB <-> BGRの変換など、ビットマップの操作にも多く使用します。

36
MrZebra
  • 列挙型のニースフラグ値の作成(手動で1、2、4 ...と入力するのではなく)
  • ビットフィールドからデータを展開します(多くのネットワークプロトコルがビットフィールドを使用します)
  • Zカーブトラバーサル
  • パフォーマンスハッキング

そして、それらが使用されている多くの場合を考えることはできません。それは通常、別の方法です-特定の問題があり、ビット操作を使用すると最良の結果が得られることがわかります(通常はパフォーマンスの面で-時間および/またはスペース)。

24
Anonymous

常にそれらを使用する1つの場所は、クロスプラットフォームアプリケーション用に整数のエンディアンネスを転置するときです。また、2Dグラフィックスをブリットするときに(他のビット操作演算子と一緒に)便利になることもあります。

14
MattK

私はそれらを数回使用しましたが、ほとんど常にバイナリファイル形式の解析に使用しました。

8
David Grant
6
Philip Reynolds

はい、まだ必要です。

たとえば、私の仕事では、シリアルポートCOMxを介してPLCと通信するためのソフトウェアを開発しています。バイト内のビットを処理する必要があります。左シフト/右シフト、および論理演算子OR、XOR、ANDを毎日使用します。

たとえば、バイトのビット3(右から左)をオンにする必要があるとします。

行う方がはるかに効率的です:

Byte B;

B := B XOR 4;

の代わりに:

Byte B = 0;
String s;  // 0 based index

s = ConvertToBinary (B);
s[5] = "1";
B := ConvertToDecimal (s);

よろしく。

ビットシフトは高速です。これらは、除算およびモジュラス演算が行われるずっと前に、CPU命令セットに実装されていました。私たちの多くは、鉛筆と紙では簡単ですが、CPUでは使用できない算術演算のビットシフトを使用しています。

例えば:

  • 大きな複合材料を素因数に分解するプロジェクトでは、ビットシフトを使用しました。
  • また、任意の大きな整数の平方根と立方根を見つけるためにビットシフトを使用しました。
6
eleven81

アセンブリ言語で書いたとき、私のコードはビットシフトとマスキングでいっぱいでした。

Cでもかなりの量でした。

JavaScriptやサーバー言語ではあまりやっていない。

おそらく最も現代的な使用法は、1と0として表されるブール値のパックされた配列をステップスルーすることです。以前は常に左シフトを使用してアセンブリの符号ビットをチェックしていましたが、より高レベルの言語では値と比較します。

たとえば、8ビットの場合、「if(a> 127){...}」で最上位ビットをチェックします。次に、左にシフト(または2を乗算)し、127で「and」を実行(または最後のビットが設定されている場合は256の減算を実行)し、再度実行します。

4
Nosredna

はい、あります。ご想像のとおり、デバイスのドライバーの開発など、低レベルのプログラミングで最もよく見られます。しかし、私はC#プロジェクトに取り組み、医療機器からデータを受信するWebサービスを開発する必要がありました。デバイスが保存したすべてのバイナリデータはSOAPパケットにエンコードされましたが、バイナリデータは圧縮およびエンコードされました。それを解凍するには、多くのビット操作を行う必要があります。たとえば、デバイスのシリアル番号が2番目のバイトの下半分であるなどの有用な情報を解析するには、多くのビットシフトを行う必要があります。また、.NET(C#)の世界では、ビットマスキングとフラグ属性の使用、私は個人的にそれをする衝動がなかった。

3
WebMatrix

数値をリトルエンディアン形式からビッグエンディアン形式に、またはその逆に変換する場合

3
Ludwig Wensauer

私はコンピューター周辺機器メーカーで働いています。毎日、ビットシフトを使用するコードに遭遇し、実装する必要がありました。

3
switchmode

うん。以前に暗号化アルゴリズムを作成する必要があり、それは間違いなくそれらを使用します。

また、ステータスを追跡するために整数などを使用する場合にも便利です。

3
kemiller2002

私は、ビットマップのビットが圧縮される画像圧縮/解凍でそれらをたくさん使いました。 http://en.wikipedia.org/wiki/Huffman_coding を使用すると、圧縮されるものはさまざまなビット数で構成され(すべてバイトアラインされているわけではありません)、したがって、ビットシフトする必要がありますそれらをエンコードまたはデコードするときに。

3
ChrisW

たとえば、C、C++などの言語での暗号化メソッドの実装。バイナリファイル、圧縮アルゴリズム、および論理リスト操作-ビットごとの操作は常に良い=)

3
Anton

ビットシフトは高レベルのプログラミングの問題を解決しませんが、低レベルの問題を解決しなければならない場合があり、それを行うためにCで別のライブラリを書く必要がないのは便利です。それが最もよく使われるのは私の推測です。

[〜#〜] ebcdic [〜#〜] 文字セットコンバーター用のエンコーダーの作成に個人的に使用しました。

3
Michael Meadows

指定された数以上の最も近い2のべき乗を求めます。

1 << (int)(ceil(log2(given)))

任意のテクスチャサイズをサポートしないハードウェアでのテクスチャリングに必要です。

2
zoul

高速フーリエ変換— FFT で、Cooley-Tukeyテクニックではビットシフト演算を使用する必要があります。

2
LicenseQ

ビットシフトは、オンラインゲームのプロトコルを解読する際によく使用されます。プロトコルは、可能な限り小さな帯域幅を使用するように設計されているため、サーバー上のプレーヤーの数、名前などをint32で送信する代わりに、すべての情報が可能な限り少ないバイトにパックされます。ブロードバンドを使用しているほとんどの人にとって、最近は本当に必要ではありませんが、当初設計されたとき、ゲームには56kモデムが使用されていたため、すべてがカウントされました。

これの最も顕著な例は、Valveのマルチプレイヤーゲーム、特にCounter-Strike、Counter-Strike Sourceにあります。 Quake3プロトコルも同じですが、Unrealはそれほどスリムではありません。

次に例を示します(.NET 1.1)

string data = Encoding.Default.GetString(receive);

if ( data != "" )
{
    // If first byte is 254 then we have multiple packets
    if ( (byte) data[0] == 254 )
    {
        // High order contains count, low order index
        packetCount = ((byte) data[8]) & 15; // indexed from 0
        packetIndex = ((byte) data[8]) >> 4;
        packetCount -= 1;

        packets[packetIndex] = data.Remove(0,9);
    }
    else
    {
        packets[0] = data;

    }
}

もちろん、これを実際のプロジェクトとして見るか、趣味(C#で)として見るかはあなた次第です。

2
Chris S

モニターのEDIDデータを読み取らなければならない組み込みシステムのプロジェクトで使用します。 EDIDの一部のデータは次のようにエンコードされます。

バイト#3:
水平ブランキング-下位8ビット
バイト#4:
下位ニブル:水平ブランキング-上位4ビット
上部ニブル:他の何か
1
Tobias Klüpfel

別の非常に一般的なことは、バイトの上位 ニブル を抽出するときに4ビットシフトを実行することです。

#define HIGH_NIBBLE(byte) (((byte) >> 4) & 0x0F)
#define LOW_NIBBLE(byte)  ( (byte)       & 0x0F)
1
hlovdal

はい、MPEG2-2トランスポートストリームパーサーで使用しました。簡単で読みやすくなりました。

1
RvdK

はい、JavaとC#アプリケーションの間でバイナリ通信を実行するとき、1つはビッグエンディアンのバイト順序で、もう1つはリトルエンディアンです(必ずしもこの順序である必要はありません)。異なるバイト順序で数値を読み取り、動作するためにバイトシフトを使用しました。

時には、ロングの4バイトに4つのショートを入れたい場合、バイトシフトを使用する場合があります。私は何年も前にそれをしたと思う...

1
Ravi Wallau

DVDディスクの.ifoファイルを解析するプログラムを作成する必要がありました。これらは、ディスクにあるタイトル、チャプター、メニューなどの数を説明するフィールドです。それらは、すべてのサイズと配置のパックされたビットで構成されています。多くのバイナリ形式では、同様のビットシフトが必要と思われます。

1
Steve Rowe

プロパティパラメータとして複数のフラグが使用されている場合、ビットごとの演算子が使用されています。たとえば、数値4 = 1 0 0は、3つのフラグのいずれかが設定されていることを意味します。これはパブリックAPIには適していませんが、ビットのチェックが高速であるため、特別な場合に速度を上げることができます。

1
Lycha

私がこれまでに書いたすべてのbitblt-erは、ビットを左右にスライドさせる機能なしでは完了できませんでした。

1
Scott Evernden

私はゲームでそれらを使用して、データカードに保存するために単一のバイト/文字に多数のフラグをパックしました。ロック解除可能なもののステータスなどの保存。最近ではそれほど多くの要件ではありませんが、作業を節約できます。

1
xan

はい、常に。 32ビット整数との間で3空間座標をパックおよびアンパックするこれらのマクロのように:

#define Top_Code(a, b, c)           ((((a) + x) << 20) | (((b) + y) << 10) | ((c) + z))                           
#define From_Top_Code(a, b, c, f)   (a = (((f) >>> 20) - x), b = ((((f) & 0xffc00) >>> 10) - y), c = (((f) & 0x3ff) - z))        
0
chaos

ポーカーハンドエバリュエーターで使用しました。

ポーカーハンドは、ハンドに存在する各カードの1ビットを持つ64ビットの符号なし整数として表されます。シフトとマスキングを組み合わせることで、「少なくとも3枚のカードを持っているランクをすべて手に入れる」などの質問をすることができます。

それはかなり高速ですが、それ以来、手がバイトの配列として表されるより高速なメソッドを学びました。

0
finnw

承知しました。 アフィニティマスク の処理では、ビットシフトを使用します。

たとえば、特定の数のプロセッサのみを使用するようにアプリケーションを制限したい場合があります(各プロセッサの使用にお金がかかるため)-アフィニティマスクのビットをカウントするためにビットシフトを使用しますか?

0
sharptooth

はい。特に、ハードウェアドライバーの制御およびステータスバイトを使用するエミュレーターで。制御バイトの各ビットには特別な意味があり、ステータスバイトの各ビットには特別な意味がありました。

0
shortbaldman

いいえ、実際に使用する必要はありません。誰かが言ったように、他の数学表現でいつでもエミュレートでき、それらはほとんど使用されないため、外部ライブラリに構築できます。ビットシフトRubyまたはpythonは、高レベルと低レベルをミックスするようなものです。

0
user35978

通常、個々の入出力値をバイトにパックする「低レベル」機器、eqデジタルイーサネットIOボックスまたはPLCと通信する場合も、ビットシフトが必要です。

0
Harriv

はい。

ビットシフティングは、メモリが不足していて速度がすべてを必要とする組み込みアプリケーションで非常に役立ちます。

たとえば、コストのかかる乗算演算を行う代わりに、加算とビットシフトのみを使用して同じ計算を実行できます。これにより、時間を大幅に節約できます。

c := 0
while b != 0
    if (b and 1) != 0
        c := c + a
    shift a left by one
    shift b right by one
return c
0
JRam930

はい、低レベルの組み込みソフトウェアでは常にビットシフトが使用されています。また、非常に高速な数学演算を実行するためのほぼ手品として使用することもできます。

http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/

0
Joonas Pulakka

私はコンピューターサイエンスを卒業しており、すでにビットシフトを使用しています。

フラグを保存したり、ハッシュを処理したりするのに適しています。

ビット単位演算を1回使用して、1つの小さな整数(2バイト)値と2つの文字を1つの整数に圧縮しました。フェローのプロジェクトに比べて、それにより多くのメモリを節約できました。

また、これらの操作は非常に高速である場合があります。タイプdoubleを拡張する必要がある場合、または関数を使用してカマキリを使用して浮動小数点データを操作する必要がある場合(浮動小数点アルゴリズムの標準を参照)。

0
Giuliano

私はかつて(何年も前に)Excel Oper構造を使用してExcelスプレッドシートを作成するプロジェクトの出力ルーチンを作成しました。これは、大量のビット調整を必要とするバイナリファイルフォルマントでした。次のリンクは、Oper構造の特色を示しています Safari Books

0
Aussie Craig

UTF-8とUTF-32間の変換を実装するために使用しました。

0
dan04

私は、新しい暗号構造でいくつかの作業を行い、シリアル化された構造(およびその後の更新)を準同型加算器の後ろに隠しました。多くのハッシュもビット操作に依存します。それらの間でシフトします。

大量のビットシフトと厄介な多数の演算が含まれます。すべてJava(確かに、これは参照/研究の実装でした)。

また、かなり頻繁にビットを圧縮する必要がある圧縮プロジェクト(特にGZIP実装)も行われました。 <<および>>(またはJavaを使用している場合は>>>)なしでそれをプルすることは想像できません。

基本的に、暗号化または圧縮を使用している場合、ある時点でビットシフトが必要になる可能性が高くなります。

0
Kevin Montrose

C#でビットシフトを実行しました。アプリは、音声サンプルレベルでいくつかの数学演算を必要とする音声オーディオ入力を正規化する必要がありました。

0
Pablote

データのほとんどのパケットはまだビットエンコードされています。あらゆる種類の低レベルのネットワーク通信を使用している場合、ビットをいじる必要があります。

また、音声とビデオを含むパケットを分析します。MP3タグでさえ数ビットを使用すると考えています。

最も重要なことは、ビット操作に慣れていないということは、いくつかの操作を実装するためのはるかに優れた方法を見逃す可能性が高いことを意味します。つまり、50億個の順序付けされたオブジェクトの存在を扱っている場合、それらをすべて簡単にramに収めて瞬時に検索できるか、このようなタスクで毎回ファイルを検索できるかが違いますビット操作をせずにそれを実装したソフトウェアエンジニアと自称している人は、彼の仕事には無能であると思います。

0
Bill K

しばらく前に、Webプロジェクトでビットシフトを使用しました。これは、各製品に多数の構成可能な属性があるeコマースアプリケーションでした。ユーザーは必要な属性を選択でき、UIが更新されて、選択したオプションの価格とSKUが提供されます。

ユーザーのオプションに一致するSKUをデータストアで検索するのではなく、オプションの各組み合わせは特定のハッシュに対応していました。これは実際にはビット演算を使用して作成された数値です。各オプションに4ビット(16の組み合わせ)、最大5つのオプションを許可したため、合計20ビットになりました。ユーザーのオプションからハッシュを計算するには、ハッシュ値に追加する各番号付き属性をループします。

for(var i = 0; i < getSku.arguments.length; i++)
{
    index = getAttributeIndex(i, getSku.arguments[i]);
    hash += (index+1) << (4*i);
}

これは、毎回最大5つの値を比較する潜在的に数百のSKUをループするよりもかなり高速でした。

0

CRC計算で使用しました。

0