「効果的なコーディングほど優れたものはありません、アミーゴ! 古いロボットを信頼してください。」

「スパイが使う暗号のことを言っているのですか?」

「もちろんそうではありません。私が話しているのは、情報をわかりやすい形式で表現することです。数値体系についてです。日常生活では、ほとんどの人が 10 進法を使用していることはご存知でしょう。十進法では、すべての数値を表すのに 10 個の記号が使用されます: 0、1、2、 3、4、5、6、7、8、9。数字が 10 個あるので、この体系を 10 進数と呼びます。」

「これは、10 本の指を持つ人間にとっては便利でした。しかし、プログラマーは偉大な発明家です。彼らはすぐに、異なる桁数を使用するエンコーディングを思いつきました。たとえば、2、8、16、または 64 桁です。彼らはこれを次のように実行しました。 「信号があるかないか」に依存するコンピューターにとって便利になります。」

「ああ、共通点がわかりました...これらのシステムはすべて 2 のべき乗に基づいています。

8進数エンコーディング

「良い観察ですね。8 桁を含むエンコーディングから始めましょう。人間はこれが最も簡単だと思うかもしれません。数字の 8 と 9 を省略するだけです。そうすれば、8 進エンコーディング (数値体系) が完成します。最近、リテラルについて説明されましたよ。 ?」

「はい、そうでした。」

「驚きました! 8 進法を使用してエンコードされた数値リテラルを設定できます。もちろん、本当に必要な場合に限ります。思っているよりも簡単です。整数の前に 0 を置くだけです

「では、数値リテラルがゼロで始まる場合、それは 8 進数であることを意味するのでしょうか?」

「はい、Java はこれを 8 進数として扱います。

例:

コード ノート
int x = 015; 
x は 13: 1*8+5
int x = 025; 
x は 21: 2*8+5
int x = 0123; 
x は 83: 1*64+2*8+3 == 1*8 2 +2*8 1 +3*8 0
int x = 078;
これはコンパイルできません。8 は 8 進エンコーディングで使用される記号の 1 つではありません。

「コードに 8 進数を記述する必要はほとんどありませんが、それが何であるかを知っておく必要があります。」 結局のところ、他の人が書いたコードを読まなければなりません。そして、上で述べたように、プログラマーは偉大な発明家です。

まあ、すべての数字の前に 0 を書き続けることはできないことを覚えておいてください。」

「でも、8 進数にするつもりなら、できるでしょうか?」

"はい。

バイナリエンコーディング

「まだ理解していなくても、バイナリエンコーディングはあなたの母国語です。思い出させてください。8 進数が 0 ~ 7 の数字しかない場合、2 進数には 0 と 1 しかありません。」

「なぜこのエンコードが必要なのでしょうか?」

「上で述べたように、これはコンピューターの内部構造にすべて関係しています。コンピューター内のすべてのものは電気で動作します。そして偶然にも、電気を使って何かを保存したり送信したりする最も効率的な方法は、次の 2 つの状態を使用することです。電線には電気は流れていません (ゼロ) が、電気はあります (1)。」

「だから人気があるのですね…うーん、確かにこの言語を覚えてきている気がします!」

「すべてのロボットはそれを完全に理解します。ただし、Java ではあまり頻繁に使用されません。Java は高級言語とみなされ、実行されるハードウェアから完全に抽象化されています。実際、データの保存と処理にどのような形式が使用されるかを本当に気にしていますか?コンピューターの中?

「しかし、過去数十年にわたり、プログラマはバイナリ エンコーディング (およびそれに基づく他のエンコーディング) を愛するようになりました。その結果、Java には入力として 2 進数を取る演算子が組み込まれています。また、浮動小数点数の精度はバイナリに依存します。」表現。

「要するに、このエンコーディングについては知らないよりも知っていた方が良いということです。」

「そうですね。8 進数エンコーディングの場合と同様、Java にはバイナリ システムを使用してリテラルをエンコードする方法があります。」

「では、0と1だけで構成されるということですか?」

「その通りです。コードに単なる 0 と 1 からなる 10 進数ではなく、バイナリでエンコードされた数値リテラルが含まれていることをJava コンパイラが理解できるように、すべてのバイナリ リテラルはプレフィックス 0b ( ' b ' はバイナリという言葉から来ています)。

例:

コード ノート
int x = 0b100; 
х は 4: 1*4+0*2+0
int x = 0b1111; 
х は 15: 1*8+1*4+1*2+1
int x = 0b1111000111; 
х は 967: 1*2 9 +1*2 8 +1*2 7 +1*2 6 +0*2 5 +0*2 4 +0*2 3 +1 *2 2 + 1*2+1;
int x = 0b12000;
これはコンパイルできません。2 はバイナリ エンコーディングで使用されるシンボルの 1 つではありません。

16 進エンコーディング

「2の4乗って何?」

「16。あなたは、私のところまでやって来たロボットに尋ねる正しい質問を思いつきました!」

「遠くまで来たようですね。とにかく、16。8 進数と 2 進数のエンコーディングに加えて、リテラルは 16 進数で書くこともできます。これは非常に一般的なエンコーディングです。

「それは、2 進数表記は実際の数値の格納方法に可能な限り近いものであるにもかかわらず、人間がそのような数値を効果的に扱うのは難しすぎるからです。2 進数では、100 万 20 桁の数値は 7 ではありません。

「それが、プログラマーが 16 進法を思いついた理由です。結局のところ、あなたが正しく指摘したように、16 は 2 の 4 乗なので、正確に 4 ビットが 1 つの 16 進数の数字に対応します。

「したがって、4 ビットごとに 1 つの 16 進数で書き込むことができるようになりました。」

「そうです。16 進エンコーディングには独自の一意のプレフィックス0xもあります。例:

10進数 2進数表記 16進数表記
17 0b 0001 0001 0x11 _ _
4 1 0b 0010 1 00 1 0x 2 9
85 0b 0101 0101 0x 5 5
256 0b 1 0000 0000 0x 1 0 0

「わかりました。8 進法をどのようにして取得したかは十分に明らかです。数字の 8 と 9 を捨てただけです。しかし、16 進法で不足している 6 桁はどこで入手できるのでしょうか? それらを見てみたいと思います!」

「すべて簡単です。英語のアルファベットの最初の 6 文字が、欠落している 6 桁と見なされます: A (10)、B (11)、C (12)、D (13)、E (14)、F (15) 。

例:

16進数表記 2進数表記 10進数
0x1 _ 0b 0000 0001 1
0x9 _ 0b 0000 1001 9
0xA _ 0b 0000 1010 10
0xb _ 0b 0000 1011 11
0xC _ 0b 0000 1100 12
0xD _ 0b 0000 1101 13
0xE _ 0b 0000 1110 14
0xF _ 0b 0000 1111 15
0x1F _ _ 0b 0001 1111 31
0xAF _ _ 0b 1010 1111 175
0x F F 0b 1111 1111 255
0x F F F 0b 1111 1111 1111 4095

「16 進数を 10 進数に変換するにはどうすればよいですか?」

「とても簡単です。 0 x A F C Fという数字があるとします。これは 10 進数でいくらになりますか? まず、位置数体系があります。これは、全体の数に対する各桁の寄与が 1 倍になることを意味します。 16 を右から左に移動すると、次のようになります。

A * 16 3 + F * 16 2 + C * 16 1 + F

記号 A は数字の 10 に対応し、文字 C は数字が 12 であることを示し、文字 F は 15 を表します。我々が得る:

10 * 16 3 + 15 * 16 2 + 12 * 16 1 + 15

16 をその数字に対応するさまざまな累乗すると、次のようになります。

10 * 4096 + 15 * 256 + 12 * 16 + 15

すべてを合計すると次のようになります。

45007

「45007 がメモリにどのように保存されるかがわかりました。」

「はい、そうです。0x A F C Fです

「では、これをバイナリに変換しましょう。バイナリでは次のようになります。

0b 1010 1111 1100 1111

「4 ビットの各セットは、正確に 1 つの 16 進文字に対応します。これは非常に便利です。乗算や累乗は必要ありません。」