初めての店舗開業を成功させよう>>

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

このQ&Aに関連する最新のQ&A

A 回答 (4件)

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が規格に入っていないのでしょうね?
 

この回答への補足

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

補足日時:2009/11/13 22:01
    • good
    • 0

> 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" 等で必要であれば調べて下さい。  
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/11/16 22:57

#1です。


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

/**
* 負数 > 正数である比較規則を定義する。
*

でした。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/11/13 22:10

う~む?こんな関数を作ってみるのも一案ですが、どっちが非効率だか判りませんね。




public class testbyte {

/**
* @param args
*/
public static void main(String[] args) {
byte[] aaa = newbyte [] {
(byte)0x00, (byte)0x01, (byte)0x02,
(byte)0x03, (byte)0x7f, (byte)0x80,
(byte)0x81, (byte)0xfe, (byte)0xff};

String[] sss = newString [] {
"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]);
intret=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
* 両方とも正数の場合は自然順序に従う
* 両方とも負数の場合は自然順序に従う
*/
publicstatic 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
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
新しい手法ですね。助かります。

しかし簡単に試してみたところ、残念ですがおおよそ3.5倍ほど遅いようでした。

お礼日時:2009/11/13 18:40

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q動的配列確保

JAVA初心者です。
VBでのRedim Preserve、CのreallocみたいなものはJAVAには無いのでしょうか?
要はあらかじめ配列数がわかっていない時に動的配列確保を行いたいのです。
Objectではなく、基本クラスのint、byte等の配列に使いたいと思っております。
ArrayListが近い事が出来そうだったのですが、Objectにしか使用出来ないので、
断念しました。教えてください。

Aベストアンサー

ラップするというのは、こんな感じです。

byte value = 1;
ArrayList list = new ArrayList();
list.add(new Byte(value));

byte や int に対応する、java.lang.Byte や java.lang.Integer などのクラスを使います。例えば new Byte(3) とやると、3 の byte 値を持つ Byte クラスのオブジェクトができます。あくまでもオブジェクトですので、そのままでは足し算や掛け算はできませんが、ArrayList にオブジェクトとして追加できるようになります。

オブジェクトから元の数値に戻すには、byteValue() や intValue() などのメソッドが各クラスに用意されているのでそれを使います。

もちろん、質問者さんが補足に書いたように、文字列に変換して ArrayList にいれる方法でもかまいません。ただし、Byte や Integer クラスのオブジェクトを使うと、
○「文字列⇔数値」の相互変換の必要が無いので、(一応)速い。
○元の数値が byte だったのか、int だったのか、short だったのか、…… が判別できる。
などの利点があります。

ラップするというのは、こんな感じです。

byte value = 1;
ArrayList list = new ArrayList();
list.add(new Byte(value));

byte や int に対応する、java.lang.Byte や java.lang.Integer などのクラスを使います。例えば new Byte(3) とやると、3 の byte 値を持つ Byte クラスのオブジェクトができます。あくまでもオブジェクトですので、そのままでは足し算や掛け算はできませんが、ArrayList にオブジェクトとして追加できるようになります。

オブジェクトから元の数値に戻すには、byteValue() や...続きを読む

QCSVファイルの中で、「 , 」カンマを使いたい

「 , 」で区切られたCSVファイルの中で、「 , 」カンマを使いたいのですが、可能でしょうか?

具体的には「これは1,500円でした。」というように、CSVファイルに収められた文章内で出てくる半角の数字(お金)の区切りに使いたいのです。
全角では代用したくないのですが、CSVファイルでデータを受け渡しする際に、困っています。

例えば、特殊文字などで対応可能でしょうか?

Aベストアンサー

受け渡しに使うと言うことは相手方のアプリケーションのことも考えなければいけないのですが・・・とりあえず対応が簡単そうな方法を。

1.各セルを""で囲む。(もちろんデータにダブルクォートがある場合はカンマと同様に困ります。
2.カンマで区切らずにタブで区切る。(比較的使われない文字ですが、やはりデータ中にタブがあるとカンマと同様です)

難しいけれど完璧に対応するためには、データ中の区切り文字は特殊な文字列に変更し、受け取り側のアプリケーションではその特殊な文字列をデータ中の区切り文字として扱うという方法が使われます。
例えば、データ中のカンマは\,にするとか。

データ作成側、受け取り側でそれぞれどこまで対応できるのか分かるともっと簡単かつ具体的な方法を回答できるかも知れません。

Qシンボルが見つかりませんというエラーが理解できません。

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Image[3];
Thread t;
int index1 = 0;
int index2 = 0;
String msg = "";
String msg1 = "";

boolean state = false;
Button b1 = new Button("ぐー");
Button b2 = new Button("ちょき");
Button b3 = new Button("ぱー");

public void init(){
for(int i = 0; i<=2; i++){
img[i] = getImage(getDocumentBase(),"hanabi" + (i+1) + ".JPG");
}
add(b1);
add(b2);
add(b3);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
msg1 = "結果は・・";

}

public void paint(Graphics g){
g.drawImage(img[index1],350,30,this);
g.drawImage(img[index2],695,30,this);
g.drawString("コンピューター",420,300);
g.drawString("あなた",800,300);
g.drawString(msg,630,320);
g.drawString(msg1,550,320);
}

public void start(){
state = true;
t = new Thread(this);
t.start();

}

public void run(){
while(state){
index1++;
if(index1 == 3){
index1 = 0;
}
index2++;
if(index2 == 3){
index2 = 0;
}
repaint();
try {
Thread.sleep(60);
}catch(InterruptedException e) { }
}
}

public void actionPerformed(ActionEvent e){
if(state == false) {
start();
return;

}
state = false;
if(e.getSource() == b1) {
msg = "ぐー";
index2 = 0;
}

else if(e.getSource() == b2){
msg = "ちょき";
index2 = 1;
}

else if(e.getSource() == b3){
msg = "ぱー";
index2 = 2;
}
check();
repaint();
}

public void check() {
if(index1 == index2) msg ="あいこ";


else if (index1 == 0) {
if(index2 == 2) msg="あなたの勝ち";
else msg ="あなたの負け";
}

else if(index1 == 1) {
if(index2 == 0) msg="あなたの勝ち";
else msg="あなたの負け";
}

else if(index1 == 2) {
if(index2 == 1) msg="あなたの勝ち";
else msg="あなたの負け";
}

}
}

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Imag...続きを読む

Aベストアンサー

「シンボルを見つけられません。」というエラーの下に何か表示がありませんでしたか?そこにヒントがあると考えられます。
シンボルを見つけられませんといエラーが表示される主な理由は4つあります。
(1)クラス、メソッド、変数などの綴りミスや定義していない変数を使用している可能性がある。
(2)コンストラクタを呼び出すときに、newを忘れている可能性がある。(3)公開されていないメンバーを呼び出している可能性がある。
(4)必要なimport文を記述し忘れている可能性がある。
ここでのあなたのエラーは(1)番ではないでしょうか?上記ではimageとなっている変数がimgになっていますね。
これはエラー表示をよく見ることで意外と簡単に解決できるのです。
ゆっくり丁寧にエラー表示を見るように心がけることが大事ですよ。


人気Q&Aランキング

おすすめ情報