【java解惑】16進数加算問題


次のコードがあります.
public class Example005 {
	public static void main(String[] args) {
		System.out.println("out1="
				+ Long.toHexString(0x100000000L + 0xcafebabe));
		System.out.println("out2="
				+ Long.toHexString(0x100000000L + 0xcafebabeL));
	}
}

出力結果:
out1=cafebabe
out2=1cafebabe

原因分析:
まず知っておきたい問題は、10進数が先頭の1元オペレータ(+/-)によって正負を表すことである.16進数、8進数、2進数はコンピュータで補符号で表される.補符号の利点は、補符号を使用して、シンボルビットと他のビットを統一的に処理することができることである.また、減算は加算で処理することもできます.また、2つの符号で表される数を加算する場合、最上位(符号ビット)にキャリーがあれば、キャリーは破棄される.上記のプログラムでは、数値0 xcafebabeはint定数であり、その最高位が置かれているため、負の数である.10進数-889275714に等しい.
out 1で実行されるこの加算は、左オペランドがlongタイプであり、右オペランドがintタイプである混合タイプの計算である.この計算を実行するために、Javaはintタイプの数値を拡張元のタイプで1つのlongタイプに変換し、2つのlongタイプの数値を加算します.intはシンボル付き整数タイプであるため、この変換は、負のintタイプの数値を数値的に等しいlongタイプの数値に引き上げる拡張子に適合する.この加算の右操作数0 xcafebabeはlong型の数値0 xffffffcafebabeLに昇格した.この数値はその後,左オペランド0 x 10000000000 Lに加算された.intタイプとして考察すると,符号拡張後の右操作数の高さ32ビットは−1であり,左操作数の高さ32ビットは1であり,この2つの数値を加算すると0となり,out 1の先頭1でなぜ失われたのかを説明する.
out 2では、0 xcafebabeLは16進数の字面常亮で表され、破壊力のあるシンボル拡張を回避するので、印刷結果も正しい.
(注:本【java解惑】シリーズは、いずれもブロガーが『java解惑』原書を読んだ後、原書の説明と例の部分を改編し、ブロガーに書いて発表したものである.すべての例は自らテストに合格し、githubに共有されている.これらの例を通じて、自分を励まし、他人に恩恵を与える.同時に、本シリーズのすべてのブロガーはブロガー個人の微信公衆番号(「愛題猿」または「ape_it」を検索する)に同期して発表される.みんなが読むのに便利です.もし文の中に原作者の権利を侵害する内容があれば、直ちにブロガーに知らせて、直ちに削除してください.読者が文の内容に異議や問題がある場合は、ブログの伝言や微信の公衆番号の伝言などを通じて共同で検討することを歓迎します.)
ソースアドレス:https://github.com/rocwinger/java-disabuse
本文は“winger”のブログから出て、転載をお断りします!