ビット単位の計算
整数に対してビット演算を実行し、結果を10進数、16進数、バイナリで表示します。
仕組み
- 2つの数字を入力: 10進数、バイナリ(プレフィックス0b)、または16進数(プレフィックス0x)で操作する値を入力します。
- 演算を選択: AND、OR、XOR、NOT、左シフト(<<)、右シフト(>>)から選択します。
- 結果を表示: 出力は10進数、バイナリ、16進数で同時に結果を表示し、ビット単位の視覚化が含まれます。
ビット演算計算機を使う理由は?
ビット演算は、システムプログラミング、暗号化、ゲーム開発、グラフィックス、ネットワーキング、組み込みシステムの基本です。AND、OR、XOR、シフトが個々のビットをどのように操作するかを理解することは、フラグの設定/解除、データのパッキング、効率的なアルゴリズムの実装に不可欠です。この計算機は、各ビットがどのように影響を受けるかを正確に確認するために、ビットレベルでの操作を示します。
機能
- すべてのビット演算子: AND(&)、OR(|)、XOR(^)、NOT(~)、左シフト(<<)、右シフト(>>)。
- 多基数入力: 10進数、バイナリ(0b…)、または16進数(0x…)で数字を入力します。
- 多基数出力: 結果は10進数、バイナリ、16進数で同時に表示されます。
- ビット視覚化: ビジュアルグリッドが、各オペランドと結果でどのビットが設定されているかを示します。
- 符号付き/符号なしモード: 8、16、32、64ビット整数間を切り替えます。
よくある質問
プログラミングでXORは何のために使われますか?
XOR(^)はビットの反転、シンプルな暗号化/難読化、一時変数なしで変数を交換、パリティチェック、ハッシュの混合に使用されます。ビットが異なる場合は1を返し、同じ場合は0を返します。
<<と>>の違いは?
左シフト(<<)はすべてのビットを左に移動し、2の累乗による乗算と同等です。右シフト(>>)はビットを右に移動し、2の累乗による除算と同等です。算術右シフトは符号ビットを保持します。論理右シフトはゼロで埋めます。
特定のビットを設定または解除するには?
ビットnを設定: value |= (1 << n)。ビットnをクリア: value &= ~(1 << n)。ビットnを反転: value ^= (1 << n)。ビットnが設定されているか確認: (value & (1 << n)) !== 0。
ブール代数からシリコンへ:ビット演算がいかにして普遍的になったか
すべての現代のCPUが実装するビット演算は、80年以上離れて発表された2つの基礎的な論文に由来します。1854年、George Booleは「An Investigation of the Laws of Thought」を発表し、二値論理の代数、AND、OR、NOT、およびそれらの恒等式を定義しました。これは哲学的な作業であり、工学的なものではありませんでした。それから1937年、21歳のMITの大学院生Claude Shannonは修士論文「A Symbolic Analysis of Relay and Switching Circuits」を書き、ブール代数が電気的なリレー回路を記述でき、したがってあらゆる論理計算が物理的に実装できることを証明しました。この論文は20世紀の最も重要な修士論文として広く引用され、すべてのデジタル電子工学の基礎です。すべてのCPUが使用する負の数のための二進表現である2の補数は、1962年にBurroughs Corporationによって特許を取得しましたが、IBM 704(1954)および他の初期のマシンですでに使用されていました。IEEE 754は1985年に浮動小数点表現を標準化し、すべてのJavaScript Numberがまだ使用しているビットレイアウトを固定しました、binary64では1符号ビット、11指数、52仮数。今日、C言語演算子& | ^ ~ << >>はほぼ直接単一のCPU命令にマップされ、これがビット演算コードが算術的等価物よりも劇的に高速になる理由です。
6つの演算子、ビットレベルで何をするか
- AND(
&)。両方の入力ビットが1の場合にのみ結果ビットは1。0b1100 & 0b1010 = 0b1000。マスクや特定のビットの分離、またはフラグが設定されているかどうかを確認するために使用:flags & FLAG_READはFLAG_READがオンの場合にゼロ以外。 - OR(
|)。いずれかの入力ビットが1の場合、結果ビットは1。0b1100 | 0b1010 = 0b1110。ビットを設定したり、フラグを組み合わせるために使用:flags = FLAG_READ | FLAG_WRITE。 - XOR(
^)。正確に1つの入力ビットが1の場合、結果ビットは1。0b1100 ^ 0b1010 = 0b0110。ビットの切り替え、単純な難読化(x ^ x = 0、つまりXORはそれ自体の逆)、パリティ、ハッシュミキシングに使用。 - NOT(
~)。すべてのビットを反転。~0b0000_1111 = 0b1111_0000(8ビット)。2の補数では、~xは-x − 1に等しいので、JavaScriptでは~5 === -6。 - 左シフト(
<<)。すべてのビットをn位置左に移動し、右側をゼロで埋める。1 << 3 === 8、2³を掛けることと同等。ビットマスクの構築に役立つ:1 << nは「位置nのビット」。 - 右シフト(
>>算術、>>>論理)。ビットを右に移動。算術シフト(JS、Java、Cの符号付きの>>)は符号ビットを保持;論理シフト(JSの>>>、Cの符号なしの>>)はゼロで埋める。-8 >> 1 === -4だが、JavaScriptでは>>>が最初に32ビット符号なしintに強制変換するため-8 >>> 1 === 2147483644。
ビット演算が実際に給料を稼ぐところ
- ビットフラグと機能トグル。32個のブール値オプションを単一の整数にパック。Linuxファイル権限(
chmod 755)、ネットワークプロトコルヘッダー(TCP、IPv4)、OpenGL状態フラグはすべてこのパターンを使用。1つの&チェックで機能が有効かどうかわかる。 - Unixファイル権限。
rwxr-xr-xは0b111_101_101 = 0o755 = 493。3つのグループはユーザー/グループ/その他、3ビットずつread/write/execute。chmod計算機は記号形式をシェルが望む整数に変換する。 - IPサブネットマスク。
/24マスクは255.255.255.0または0xFFFFFF00。IPがサブネット内にあるかチェック:(ip & mask) === (network & mask)。世界中のすべてのルーターとファイアウォールで使用。 - 暗号と ハッシュ。 SHA-256、AES、ChaCha20、BLAKE3、すべての現代のハッシュと暗号は主にAND、OR、XOR、NOT、回転から構築。XOR単独はワンタイムパッドの基礎であり、キーが真にランダムで一度使用される場合、証明可能に解読不可能。
- 色の操作。 32ビットRGBA色は4つの8ビットチャネルをパック:
(R << 24) | (G << 16) | (B << 8) | A。赤チャネルを抽出するには:(color >> 24) & 0xFF。HTMLキャンバス、OpenGL、すべての画像形式で使用。 - パフォーマンスのトリック。ほとんどのCPUで
x & 1はx % 2よりはるかに高速(1サイクル対~10)。x >> 1は1サイクルで2で割る。2の累乗のアラインメント、ビット-population数、ビット-twiddlingハックはパフォーマンスクリティカルなコードのどこにでもある。(有名なカタログについてはSean Andersonの「Bit Twiddling Hacks」ページを参照。) - 組み込みシステム。マイクロコントローラはハードウェアレジスタをメモリ内の特定のビット位置にマップする。UARTやGPIOピンを構成するには、残りを乱さずに正しいビットを読み書きするためにマスキングとシフトが必要。Cのビットフィールド構文はこれらのパターンの便利なシュガー。
噛むミス
&と&&、|と||を混同する。単一の形式はビット演算、二重は短絡論理。1 & 2 === 0(共有ビットなし)だが1 && 2 === 2(両方真、2番目を返す)。それらを混同すると、条件付きロジックが静かに壊れる。- 演算子優先順位の驚き。
x & FLAG === 0はx & (FLAG === 0)を意味し、(x & FLAG) === 0ではない、===が&よりきつく結合するため。条件のビット演算式は常に括弧で囲む。 - 符号付きvs符号なしシフトの混乱。 JavaScriptでは
>>は算術(符号拡張)、>>>は論理(ゼロ埋め)。Cは変数の型で区別、符号付き型は算術、符号なしは論理を使用。JavaはJavaScriptと同様に>>と>>>の両方を持つ。言語の規約に一致しないと、静かに意味が反転する。 - JavaScriptはビット演算のために32ビットに切り詰める。
Numberが64ビット浮動小数点であるにもかかわらず、すべてのビット演算子は最初にオペランドをint32に強制変換。0x100000000 & 0xFF === 0、0 + 下位バイトではない、ANDの前にオペランドが32ビットに切り詰められるため。64ビットビット操作にはBigIntを使用、独自のビット演算子を持つ。 - JavaScriptで> 31でシフト。
1 << 32 === 1、0ではない。シフト量は32で割った余りが取られる。Cはさらに危険:ビット幅より大きくシフトすることは未定義の動作、コンパイラは何でもできる。実行時の値でシフトする前に常にn < bitWidthをチェック。 - バイトパッキングコードでのエンディアンネス。
(r << 24) | (g << 16) | (b << 8) | aは0xRRGGBBAAを生成。バイトがその順序で格納されるか、メモリで逆になるかはプラットフォームによる。HTMLキャンバスのImageDataはx86でリトルエンディアン;PNGファイル形式はビッグエンディアン。バイナリ形式を読み取る際はDataViewで明示的に変換。 - 2の補数を忘れる。
~0 === -1、0xFFFFFFFFではない、すべて1は−1の2の補数エンコーディングだから。JavaScriptで符号なし32ビット解釈を得るには:(~0) >>> 0 === 4294967295。
なぜ2の補数か、そしてビットレベルでは何を意味するか
すべての現代のCPUは2の補数を使用して負の整数を表現する。符号付き8ビットバイトでは、値0から127はバイナリ0000_0000から0111_1111としてエンコードされる。次に−1は1111_1111として、−2は1111_1110として、最大−128は1000_0000としてエンコードされる。理由:このエンコーディングでは、入力が符号付きか符号なしかに関わらず加算は同じように動作し、CPUは別々のadd-signedとadd-unsigned命令を必要としない。非対称性は、負の範囲が正の範囲より1つ大きいことであり(8ビットでは−128から+127)、これが固定幅整数を持つすべての言語でMath.abs(INT_MIN)がオーバーフローする理由。以前の符号-絶対値(符号に1ビット、残りは大きさ)と1の補数エンコーディングは1950-60年代に存在したが、ゼロの2つの表現を持ち、否定のための特別なケースのハードウェアを必要としたため、2の補数に負けた。
その他のよくある質問
なぜ~5は250ではなく-6に等しいのか?
2の補数(すべての現代のCPUが使用するエンコーディング)では、正の数のすべてのビットを反転すると-n - 1が得られるから。したがって~5 === -6と~0 === -1。符号なし8ビットコンテキストでは、~5と同じビットパターン(バイナリ1111_1010)は250を表す。JavaScriptは結果を符号付き32ビットとして扱うので、-6が表示される。符号なしの解釈を得るには:32ビットで(~5) >>> 0、これは4294967290を与える、または~5 & 0xFFで8ビットにマスクして250を得る。
XORは本当に暗号化なのか?
XORはすべての現代の対称暗号の構成要素ですが、XOR単独は安全な暗号化ではありません。ワンタイムパッド、メッセージと同じ長さの真にランダムなキーとのXOR、正確に一度使用、は情報理論的に解読不可能(Shannon、1949)。キーを再利用したり、メッセージより短いキーを使うと、頻度分析でそれを簡単に破る。AESのような実際の暗号は、短いキーをキーなしの人にワンタイムパッドのように見える擬似ランダムバイトストリームに増幅するために、XOR、拡散、置換を使用。なので「XORで暗号化」は些細な難読化にのみ良い、本当の秘密には決してない。
ビット操作のためにNumberの代わりにBigIntを使用すべきはいつか?
32ビット以上のビット演算精度が必要なときはいつでも。JavaScriptビット演算子は計算前にNumberオペランドを32ビット符号付き整数に切り詰める。64ビットマスクが必要な場合(例:64ビット機能フラグセットの操作、Linux mmapオフセットでの作業、またはSHA-512の実装)、BigIntを使用:0xFFFFFFFFFFFFFFFFn & 0xFFn === 255n。BigIntはNumberより遅く、操作によって~3-10×、なので32ビットが真に少なすぎるケースのために予約する。
数の中の1ビットの数をどう数えるか?
これは人口カウントまたはハミング重み。ほとんどの現代のCPUにはそれのための単一の命令がある(x86のPOPCNT、ARMのVCNT)。JavaScriptには組み込みがないので、ビット-twiddlingクラシックを使用:let c = 0; while (x) { c += x & 1; x >>>= 1; }。またはHacker's Delightの並列SWARトリック:x = x - ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0F0F0F0F; return (x * 0x01010101) >>> 24;、これは32ビット整数のビットを約12サイクルで数える。
この計算機を使用するとき、私のデータはどこかに送信されるか?
いいえ。すべての操作はブラウザのJavaScriptエンジンで実行され、計算中にネットワーク呼び出しは発生しません。DevToolsでネットワークタブを開いてCalculateをクリックすると、アウトバウンドリクエストがゼロ表示される。機密マスク、キー、または独自のビットレイアウト作業に対して安全。