C、C++、Java ではバイナリ表現に 2 つの補数を使用していると聞きました。1補数を使用しないのはなぜですか? 1補数よりも2補数を使用する利点はありますか?
8 に答える
2 の補数の符号付き整数を使用すると、はるかにクリーンになります。基本的に、追加のキャリーの追加を明示的に処理する必要はなく、符号付きの値を符号なしであるかのように追加して、期待どおりに動作させることができます。2 の補数には 0 の値が 1 つしか含まれないのに対し、1 の補数では正のゼロと負のゼロの両方を定義できるため、値が 0 かどうかを確認するのも簡単です。
追加キャリーの追加については、小さい負の数に正の数を追加することを考えてください。1 の補数表現のため、符号なしの量として見ると、小さい負の数は実際にはかなり大きくなります。2 つを加算すると、キャリー ビットでオーバーフローが発生する可能性があります。符号なし加算とは異なり、これは必ずしも値が大きすぎて 1 の補数で表現できないことを意味するわけではなく、表現が一時的に利用可能なビット数を超えたというだけです。これを補うには、2 つの 1 の補数を加算した後にキャリー ビットを追加します。
数値の内部表現は、これらの言語の一部ではなく、マシン自体のアーキテクチャの機能です。ほとんどの実装では、2 の補数を使用します。これは、加算と減算を同じ 2 進数演算にするためです (符号付き演算と符号なし演算は同じです)。
The answer is different for different languages.
In the case of C, you could in theory implement the language on a 1's complement machine ... if you could still find a working 1's complement machine to run your programs! Using 1's complement would introduce portability issues, but that's the norm for C. I'm not sure what the deal is for C++, but I wouldn't be surprised if it is the same.
In the case of Java, the language specification sets out precise sizes and representations for the primitive types, and precise behaviour for the arithmetic operators. This is done to eliminate the portability issues that arise when you make these things implementation specific. The Java designers specified 2's complement arithmetic because all modern CPU architectures implement 2's complement and not 1's complement integers.
For reasons why modern hardware implements 2's complement and not 1's complement, take a look at (for example) the Wikipedia pages on the subject. See if you can figure out the implications of the alternatives.
これは宿題の質問ですか?もしそうなら、1 の補数系で 0 を表現する方法を考えてみてください。
~
少なくとも C と C++ は、言語の演算子を介して 1 の補数否定 (ビットごとの否定と同じ) を提供します。ほとんどのプロセッサ (および最新のすべてのプロセッサ) は、次の理由から 2 の補数表現を使用します。
- 正数と負数の加算は、符号なし整数の加算と同じです
- 0 の 2 つの表現 (+0 と -0) による「無駄な」値がない
編集: C++0xのドラフトでは、符号付き整数型が 1 の補数か 2 の補数かを指定していません。つまり、以前のバージョンの C および C++ で指定されていた可能性はほとんどありません。あなたが観察したのはimplementation-defined behaviorです。これは、パフォーマンス上の理由から、少なくとも最新のプロセッサでは 2 の補数です。
ほとんどすべての既存の CPU ハードウェアは 2 の補数を使用しているため、ほとんどのプログラミング言語も 2 の補数を使用していることは理にかなっています。
C および C++ は、ハードウェアが提供する場合、1 の補数をサポートします。
ゼロと丸めに関係しています。1 番目の補数を使用すると、ゼロが 2 つになる可能性があります。詳細については、こちらを参照してください。
数値コードの場合は、符号と大きさの表現の方がはるかに優れています。対称性の欠如は、2 の補数の実際の問題であり、多くの有用な (数値指向の) ビットハックも妨げます。2 の補数は、算術演算で思ったような結果が得られないというトリックな状況ももたらします。したがって、分割、シフト、否定に関して注意する必要があります。