ぺんぎんらぼ

お笑いとマンガ好きなしょぼしょぼWeb系エンジニアの日記です。たまに絵を描きます。

お笑いとマンガ好きなしょぼしょぼWeb系エンジニアの日記です

Javaでbyte型の値を比較するときに注意すること

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("ミとムは等しいです。");
}

結果は期待通り、

ミはムより小さいです。

と表示されます。