• ベストアンサー

byte変数の大小を効率よく比較したい

2つのbyte変数の比較を行いたいのですが、 byte aaa = 0x00; byte bbb = (byte)0xff; if(aaa > bbb){ 処理 } のようにするとbyteの最上位bitは符号として扱われるため 0xff=-127となってしまい意図した結果が得られません。 unsigned byteなるものがあれば都合がよいのですが、javaではサポートしておらず困っております。 代替案として、 if(aaa&0xff > bbb&0xff) などとして、一度intへ変換後比較すれば可能ですが、int用のメモリ領域を作成しなくてはならず、非効率の気がします。 byte変数の比較で、他に効率のよい方法はりませんでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • ninoue
  • ベストアンサー率52% (1288/2437)
回答No.3

f(aaa&0xff > bbb&0xff) このままで良いですよ。 JavaVMが実行時にレジスタ内部で(aaa & 0xff)の演算を、bbbについても同じくやった後、直接レジスタ同士の比較をやるように、各マシン毎にマシン命令に変換しますから、そのままが一番早いはずです。 従ってこの演算用のint用のメモリ領域は不要です。 unsigned byte,int等が無いためにa=0x12,b=0x81の2バイトから (a<<8)|b ==>0xff81が得られて困っている人がいたりします。 何でunsigned byte,int,long dataが規格に入っていないのでしょうね?  

qunixx
質問者

補足

ご回答ありがとうございます。 そうですか。ではこのままが一番でファイナルアンサーなのですかね。 同処理を何百単位で繰り返し実行させた場合、JITコンパイルされる事を考えると、Cで同じ事をさせた場合と同じような結果を期待したのですが、Javaの方が数倍遅い結果となりました。これは byte->int処理部が効いてしまっているのですかね。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • ninoue
  • ベストアンサー率52% (1288/2437)
回答No.4

> byte->int処理部が効いてしまっているのですかね。 そのようですね。 C の場合は load reg,aaa; comp reg,bbb の2命令で Java の場合 load reg0,aaa; (if not sign extended load & aaa>0x7f, sign extend) andi reg0,0xff load reg1,bbb ... comp reg0,reg1 のようになると思います。 (...) の部分は後に続くのがバイトマスク命令であれば省けるはずですが、無条件にsign extended 32bit int に変換するだけだったらそのまなので時間がかなり余分にかかるでしょうね。 "java 逆アセンブラ"、"java 逆コンパイラ", "java virtual machine specification", "java JIT compiler" 等で必要であれば調べて下さい。  

qunixx
質問者

お礼

ご回答ありがとうございます。 逆アセしてもうすこし深くさぐってみたいと思います。 ありがとうございます。

すると、全ての回答が全文表示されます。
回答No.2

#1です。 ちょっとお詫びと訂正。 /** * 偶数 > 奇数である比較規則を定義する。 * ではなく、 /** * 負数 > 正数である比較規則を定義する。 * でした。

qunixx
質問者

お礼

ご丁寧にありがとうございます。

すると、全ての回答が全文表示されます。
回答No.1

う~む?こんな関数を作ってみるのも一案ですが、どっちが非効率だか判りませんね。 public class testbyte { /** * @param args */ public static void main(String[] args) { byte[] aaa = new byte [] { (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x7f, (byte)0x80, (byte)0x81, (byte)0xfe, (byte)0xff }; String[] sss = new String [] { "00", "01", "02", "03", "7F", "80", "81", "FE", "FF" }; for(int lp=0;lp<aaa.length;lp++){ for(int i=0;i<aaa.length;i++){ System.out.print(sss[lp]); int ret= compare(aaa[lp],aaa[i]); if(ret<0){ System.out.print(" < "); }else if(ret>0){ System.out.print(" > "); }else{ System.out.print(" = "); } System.out.println(sss[i]); } } } /** * 偶数 > 奇数である比較規則を定義する。 * * @param i1 比較する最初の項 * @param i2 比較する二番目の項 * @return i1 が負数かつ i2 が正であれば 1 * i1 が正数かつ i2 が負数であれば -1 * 両方とも正数の場合は自然順序に従う * 両方とも負数の場合は自然順序に従う */ public static int compare(byte i1, byte i2){ if((i1<0) && (i2>=0)) return 1; if((i1>=0) && (i2<0)) return -1; return (i1 - i2); } } 00 = 00 00 < 01 00 < 02 00 < 03 00 < 7F 00 < 80 00 < 81 00 < FE 00 < FF 01 > 00 01 = 01 01 < 02 01 < 03 01 < 7F 01 < 80 01 < 81 01 < FE 01 < FF 02 > 00 02 > 01 02 = 02 02 < 03 02 < 7F 02 < 80 02 < 81 02 < FE 02 < FF 03 > 00 03 > 01 03 > 02 03 = 03 03 < 7F 03 < 80 03 < 81 03 < FE 03 < FF 7F > 00 7F > 01 7F > 02 7F > 03 7F = 7F 7F < 80 7F < 81 7F < FE 7F < FF 80 > 00 80 > 01 80 > 02 80 > 03 80 > 7F 80 = 80 80 < 81 80 < FE 80 < FF 81 > 00 81 > 01 81 > 02 81 > 03 81 > 7F 81 > 80 81 = 81 81 < FE 81 < FF FE > 00 FE > 01 FE > 02 FE > 03 FE > 7F FE > 80 FE > 81 FE = FE FE < FF FF > 00 FF > 01 FF > 02 FF > 03 FF > 7F FF > 80 FF > 81 FF > FE FF = FF

qunixx
質問者

お礼

ご回答ありがとうございます。 新しい手法ですね。助かります。 しかし簡単に試してみたところ、残念ですがおおよそ3.5倍ほど遅いようでした。

すると、全ての回答が全文表示されます。

関連するQ&A