byte型の値の範囲
Javaのbyte型は1バイトで値を表現する方です。
大事なことは「符号付整数」である点です。
表現できる値の範囲は -128~127 になります。
何をいまさら、と思うかもしれませんが、意外と実装するときに忘れがちです。
byte型の値の比較
次のコードを実行してみましょう。byte型の値 0x7f(127)と0x80(128)を比較するコードです。
byte b1 = (byte) 0x7f; byte b2 = (byte) 0x80; if (b1 < b2) { System.out.println("0x7fは0x80より小さいです。"); } else if (b1 > b2) { System.out.println("0x7fは0x80より大きいです。"); } else { System.out.println("0x7fと0x80は等しいです。"); }
結果は、
0x7fは0x80より大きいです。
と表示されます。
0x80は1バイトで表現できる値なので、桁あふれしているわけではありません。
原因は、byte型は「符号付整数」である点です。
0x80はbyte型では128ではなく、-128になります。よって、0x7f(127)と0x80(-128)を比較した結果、「0x7fは0x80より大きいです。」になります。
byte型の値を符号なし整数として比較する方法
byte型の値を「符号なし整数」に変換したうえで比較する必要があります。
byte b1 = (byte) 0x7f; byte b2 = (byte) 0x80; if (Byte.toUnsignedInt(b1) < Byte.toUnsignedInt(b2)) { System.out.println("0x7fは0x80より小さいです。"); } else if (Byte.toUnsignedInt(b1) > Byte.toUnsignedInt(b2)) { System.out.println("0x7fは0x80より大きいです。"); } else { System.out.println("0x7fと0x80は等しいです。"); }
結果は期待通り、
0x7fは0x80より小さいです。
と表示されます。
byte型配列の値の比較
次のコードを実行してみましょう。全角の「ミ」と「ム」をShift JISの辞書順で比較するコードです。
比較自体はバイト配列を比較するArrays#compareメソッドを使用しています。
byte[] b1 = "ミ".getBytes("cp943"); byte[] b2 = "ム".getBytes("cp943"); int result = Arrays.compare(b1, b2); if (result < 0) { System.out.println("ミはムより小さいです。"); } else if (result > 0) { System.out.println("ミはムより大きいです。"); } else { System.out.println("ミとムは等しいです。"); }
結果は、
ミはムより大きいです。
と表示されます。
「ミ」のShift JISコードは0x83 0x7e、「ム」。 のShift JISコードは0x83 0x80です。1バイト目はどちらも0x83なので、2バイト目の0x7eと0x80を比較した結果が反映されます。
0x7eと0x80をbyte型の「符号付整数」として比較されてしまうことで、期待通りの比較結果になりません。
byte型の値を符号なし整数として比較する方法
byte型の値を「符号なし整数」に変換したうえで比較する必要があります。 Arrays#compareUnsignedメソッドを使用することで、byte型配列の値を「符号なし整数」として比較することができます。
byte[] b1 = "ミ".getBytes("cp943"); byte[] b2 = "ム".getBytes("cp943"); int result = Arrays.compareUnsigned(b1, b2); if (result < 0) { System.out.println("ミはムより小さいです。"); } else if (result > 0) { System.out.println("ミはムより大きいです。"); } else { System.out.println("ミとムは等しいです。"); }
結果は期待通り、
ミはムより小さいです。
と表示されます。