• ベストアンサー

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変数の比較で、他に効率のよい方法はりませんでしょうか?

  • Java
  • 回答数4
  • ありがとう数6

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

  • ベストアンサー
  • 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

  • byte[2] から int へ。

    それぞれintの下位2バイトのビット列保持するbyte型配列の要素2つを int 形の整数に治したいのですがいい方法が思いつきません。例えば、 byte[0] = 0x01; byte[1] = 0x01; ならば、 00000000 00000000 00000001 00000001 で、256 + 1 = 257 byte[0] = 0x02; byte[1] = 0x10; ならば、 00000000 00000000 00000010 0000011 で、512+3 = 515 です。byteの値が0~127の場合は int n = byte[0] << 8 n = n | byte[1] という感じでいけそうなのですが、byte[0]が 0xFF のような負の値のときにint とのビット演算(もしくはシフト演算)で上位2バイト分も補数表記のためか全部1で埋まってしまい、上の方法はだめみたいです。 byte[0] = 0x01; byte[1] = 0xFF; のときは、 00000000 00000000 00000001 11111111 で、256+255 = 511 としたいのですが、場合わけをせずに求める よい方法はないでしょうか。

    • ベストアンサー
    • Java
  • 値の比較を効率よく行う方法を教えてください

    最近、Perlによるプログラミングを始めました。 いろいろ学習していて不明なことがあったので、質問させていただきます。 比較による処理の分岐で、毎回比較する変数名と値は決まっています。 変数には、if文の外でforなどの処理により毎回違う値が格納されています。 このとき、何も考えずに力技で書けば if ($value eq 'aaa' || $value eq 'bbb' || $value eq 'ccc' || $value eq 'ddd' ||・・・){ # 処理 } となると思います。 これでも、処理はできるのですが、比較する値が少ないうちはいいですが、多くなったとき効率が悪いと思います。 それに、スマートではないですし・・・。 これを、効率よく処理なおかつスマートに書ける方法があれば、教えてやってください。 初心者の質問で申し訳ないですが、よろしくお願いします。

    • ベストアンサー
    • Perl
  • MicroC コンパイラ 変数宣言

    MicroC コンパイラ 変数宣言について質問です BYTE tmp1; WORD tmp2; なる定義があったとして 変数型範囲はどの範囲になるのでしょう 下記の定義は見つかったのですが 上記は分かりません 変数型 バイト数 範囲 (unsigned) char 1 0 .. 255 signed char 1 - 128 .. 127 (signed) short (int) 1 - 128 .. 127 unsigned short (int) 1 0 .. 255 (signed) int 2 -32768 .. 32767 unsigned (int) 2 0 .. 65535 (signed) long (int) 4 -2147483648 .. 2147483647 unsigned long (int) 4 0 .. 4294967295 float 4 ±1.17549435082 * 10-38 .. ±6.80564774407 * 1038 double 4 ±1.17549435082 * 10-38 .. ±6.80564774407 * 1038 long double 4 ±1.17549435082 * 10-38 .. ±6.80564774407 * 1038

  • 変数の扱える範囲

    C言語で、整数型変数の扱える範囲を確認するために 以下のような処理をしているのですが、どうもうまくいきません。 変数に入りうる最大値の値を、2進数の計算ではなく プログラム内で正しく扱われているか確認する方法はないでしょうか? ご存知の方、教えてください<(_ _)> 宜しくお願いいたします。 **********************************************  unsigned long long I; unsigned long A; unsigned int B; unsigned short C; printf("I:%d A:%d byte B:%d byte C:%d byte \n"    ,sizeof(I),sizeof(A),sizeof(B),sizeof(C)); A = B = C = 0; for(I = 0; I <= 4294967295; I++){ A++;B++;C++; if(I>= 4294967290 && I<= 4294967295)    printf("I:%d A:%d B:%d C:%d\n",I,A,B,C); }

  • 値のコピーについて

    お世話様です。 unsigned long aaa(32bit)にunsigned char bbb[4](8bit*4)を コピーする場合に、(1)と(2)で結果が違うのはなぜでしょうか? よろしくご教授お願いいたします。 (1)memcpy(&aaa bbb, 4); (2) { aaa = 0; unsigned long ccc = 0; ccc = static_cast<unsigned long>bbb[0]; aaa |= ((ccc << 24) & 0xFF000000); ccc = static_cast<unsigned long>bbb[1]; aaa |= ((ccc << 16) & 0x00FF0000); ccc = static_cast<unsigned long>bbb[2]; aaa |= ((ccc << 8) & 0x0000FF00); ccc = static_cast<unsigned long>bbb[3]; aaa |= ((ccc << 0) & 0x000000FF); } 【環境】CPU:Pentimum4 OS:WindowsXP コンパイラ:VC++8.0

  • c++のグローバル変数

    お世話になります c++のグローバル変数の使い方を教えていただけないでしょうか Visual Studio 2008を使用しております ------------abc.cpp------------- int AAA; BBB(){ AAA = 1; } abc::CCC(){ AAA = 2; } コンパイル(ビルド)ではエラーは出ないのですが、 BBBをコールした時は変数AAAに値をセットできるのですが、 abc::CCCをコールした時、AAAに値がセットできません、 ウォッチ等も「エラー:識別子'AAA'はスコープ外です」 となってしまいます。 補足 BBBはリンクしているライブラリ(修正不可)からコールされる為、 クラスに組み込む事が出来ません。

  • Perlでの比較表現について

    度々失礼します。 Perlでの比較表現について、例えば $a=aaa,bbb,ccc,ddd; $b=aaa,bbb; if($a =~ $b){ print "include!"; } としたときの結果は include! となり、比較に合致するのですが、 $a=aaa,\[bbb\],ccc,ddd; $b=aaa,\[bbb\]; if($a =~ $b){ print "include!"; } という条件で実行すると、比較に合致せず何も表示されません。 こういった場合、どのように対処すればよろしいでしょうか。 ご存じの方がおられましたらご教授下さい。

    • ベストアンサー
    • Perl
  • 多次元配列?配列のキー?変数の型?

    PHP勉強中のものです。 予定通りの動作にならんく四苦八苦しています。 どのように修正すれば予定通りになるのか考え方のアドバイスなどお願いします。 処理したいこと 変数$xxxの先頭の文字と最後の文字をsubstr()で取り出し$aaaと$bbbに別けそれぞれ代入しキーとして多次元配列に代入した配列要素を指定してechoで出力したい 試してみたこと $aaa1と$bbb1に直接整数を代入してみたところ、echoで出力された キーになる変数を整数型として変数に代入してみたが希望通りの動作にならなかった。 なにかアドバイス頂けると助かります。 $array = array( "0" =>array("あいうえお","かきくけこ"), "1" =>array("さしすせそ") ); $xxx = "0-1"; $aaa = substr($xxx,0,1); $bbb = substr($xxx,2); $aaa = (int)$aaa; $bbb = (int)$bbb; echo $array[$aaa][$bbb]; //出力されない $aaa1 = 0; $bbb1 = 1; echo $array[$aaa1][$bbb1]; //出力された $aaa = (int)$aaa; $bbb = (int)$bbb; echo $array[$aaa][$bbb]; //出力されない

    • ベストアンサー
    • PHP
  • 変数を動的に利用するには?

    Javaプログラミングの質問です。 下記のように変数を定義しておき、 String aaa_0 = "AAA1"; String aaa_1 = "AAA2"; 例えば、これらの変数の値を次のようにして使えますでしょうか? (できませんが、やりたいことは、なんとなく伝わったかと思います。) for(int i=0;i<2;i++){ System.out.println("aaa_" + i); } 変数を動的に呼び出せますでしょうか? アドバイスお願い致します。

  • 128ビット変数の符合表現について

    C言語で符号付128ビット変数を4つの32ビット変数(signed longまたはunsigned long)で表現したいと思っています。 この場合32ビット変数の符合付き/符合なしはどのように組み合わせるのが適切なのでしょうか。 一応3通りの方法を考えてはみました。 (1)が適切な気もするのですが違う気もします。 アドバイスをお願いします。 (1) 最上位32ビット変数をsigned longにして残りの3つの32ビット変数はunsigned longにする。 (2) 4つの32ビット変数を全てsigned longにする。 (3) 4つの32ビット変数を全てunsigned longにする。

専門家に質問してみよう