- PR -

奇数、偶数の判断の方法

投稿者投稿内容
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2003-12-05 11:43
i & 1 はビット演算をしています。
たとえば、3 は2進数で表すと 0011 、4 は同じく 0100 となります。
これと 0001 を AND 演算するので、
  0011
AND 0001
--------
  0001

  0100
AND 0001
--------
  0000

となります。
#2進数や論理演算がよくわからなかったら、なんか参考書をあたってください。

つまり 0001 と AND 演算した結果が 0001 であれば(最下位ビットが立っていれば)奇数であると判断できるのです。ちょっとコンピュータ寄りの考え方で一見わかりにくいのですが、2で割って余りを比較するよりは早く処理できます。

もっとも、javac なり JVM の最適化具合によっては結局同じ処理をしてくれる可能性もありますし、実際の処理速度の差は微々たるものなので自己満足に近いものもあります。

アセンブリ言語や C 言語では結構普通にこういうプログラムをします。
うろ覚えですが、例えば Z80 では
LD A 3 //A レジスタに 3 を代入
RLCA //A レジスタを右にシフト 最下位ビットはキャリーフラグへ
JR NC odd //キャリーフラグが立っていなければラベル odd: へ
//奇数の処理
odd:
//偶数の処理

というように書きます。全然意味わかりませんよね?Java では処理速度の向上は Javac/JITコンパイラにまかせて、人間はメンテナンス性の良さを重視する傾向にあるので、素直に i % 2 == 0 と書くか、このような凝った書き方する場合はしっかりコメントを書いた方が良いですね。

[ メッセージ編集済み 編集者: インギ 編集日時 2003-12-05 11:54 ]
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-12-05 14:43
ほむらです。
オフトピですが。。。
--------------
新人さんにプログラム(の文法)を教えていたときに
論理演算子(&&,||)とビット演算子(&,|)の区別をなかなか理解してもらえずに
説明でかなり悩んだことがあります。

論理演算子は論理式(条件文)を書くときに使って
ビット演算子は算術式(計算式)で使うんだよー
とかなり砕いた(ある意味いいかげん)いいかたで
うなづいてはいましたが、果たして理解していたのか今も謎です。

#ビット演算は時々便利だったりするので覚えておいて損はないですよね。
begood
ベテラン
会議室デビュー日: 2003/09/12
投稿数: 97
お住まい・勤務地: とうきょー
投稿日時: 2003-12-06 01:04
失礼しました。私の大変勘違いでした。ビット演算の話ですね。 (i & 1)のあとに==0があるのに築かず、すいません。

下記は無視してください。
===================================

ボムさんが聞かれているのはCとJAVAの違いではないでしょうか・・・。(私がスーパー勘違いしていたらすいません)
-------------------------
if((i & 1) == 0){
//偶数
}else{
//奇数
}
--------------------------
ビット演算をして、ifの括弧のなかが0になれば偽、1であれば真です。
JAVAはtrueかfalseにしないといけないんですよね?(ちょっと自信なく・・・、違っていたら訂正願います)なので、Cの場合であれば(i & 1)とビット演算しているわけです。

ちなみに、Cのコードは下記の感じになります。(ちょっと、ここの掲示板に乗せるのは気が引けますが・・・)コンパイラがあったら試してみてください。(当たり前のことですが、コンソールに表示できるコンパイラで試してくださいね。昔、コンソールに表示できないCのコンパイラを使用していたことがあって、苦労したことがあります。(お恥ずかしい・・・))
#include<stdio.h>

main(void){
int i1 = 0;
int i2 = 1;
if(i1){
printf("i1 : 0");
}
if(i2){
printf("i2 : 1");
}
}



[ メッセージ編集済み 編集者: begood 編集日時 2003-12-06 01:23 ]
syo
常連さん
会議室デビュー日: 2003/08/17
投稿数: 43
投稿日時: 2003-12-06 11:49
お世話になっております。

元のスレッドの内容とはずれてしまいますが、

引用:

ほむらさんの書き込み (2003-12-05 14:43) より:

#ビット演算は時々便利だったりするので覚えておいて損はないですよね。



DBのint型のフィールドに、複数のフラグ状態を保存するときに使用していたりします。

DBから取得したときに、目的のフラグが立っているかどうかを、
if ((flag & 0x1) == 0x1) {
} else if ((flag & 0x2) == 0x2) {
}
・・・のような感じでチェック。
ボム
ベテラン
会議室デビュー日: 2003/07/25
投稿数: 61
投稿日時: 2003-12-08 09:16
人様のスレッドで質問してしまい、すみませんでした。
こーゆー場合は別にスレッドを立てるべきでした。

皆さんのご説明が非常にわかりやすく、理解できました。
ただ、私に使えるかは微妙ですが・・・

ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-12-08 14:01
ども、ほむらです。
-------
syo氏へ
僕もフラグの管理でビット演算は良く使用していました。(C++)
えと、主な使い方としては
1.取得でAND
2.設定でOR
3.トグルスイッチでXOR
あとは画像の加工ですか(笑
アルファブレンディングとかぼかしとか。。。ですね

僕の場合フラグそのものは別途定義してましたが。。。
if ((flag & BIT1 ) != 0) { とか
複数の状態を一つの条件でかけるのもビット演算の便利なところですね
if ((flag & (BIT1 | BIT2) ) != 0) {

ボム氏へ
他の方も言ってらっしゃいますが
ビット演算を使用したところでたいした速度の向上は見込めません。
特にJavaの場合バイナリデータの扱いそのものが苦手なようですし。。。
(アプリ特化した言語だけに必要ないのかも?)
最近だと言語によっては、コントロール単位で変数を一つつけて
自動的に関連性をもたせてくれていたりしますしねー

なので積極的に利用していく必要性はないと僕も考えますが
トレースするときの知識として持っていて損はないかなと。。。>ビット演算(とくにマスク処理)
begood
ベテラン
会議室デビュー日: 2003/09/12
投稿数: 97
お住まい・勤務地: とうきょー
投稿日時: 2003-12-12 11:47
古いスレッドですいません。
一番最初に言われている部分、同じ現象が私のところでもでました・・・。どうしてなのか・・・。負数は2で割ると問題があるのでしょうか?
どうしても、負の数で奇数にたどり着けません。absで行えば問題はないと思うのですが、ちょっと考え込んでしまい・・・意見を聞きたく。それとも、このコードが単純な部分で間違っていたら、アドバイス願います。

public void show1(){
Random ran1 = new Random();
int i1 = ran1.nextInt();
int flag1 = i1%2;
System.out.println(i1);

if(i1>0){
if(flag1 == 0){
System.out.println("正:偶数");
}
if(flag1 ==1){
System.out.println("正:奇数");
}
}
if(i1<=0){
if(flag1 == 1){
System.out.println("負:奇数");
}
if(flag1 == 0){
System.out.println("負:偶数");
}
}
}
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2003-12-12 12:02
引用:

begoodさんの書き込み (2003-12-12 11:47) より:

古いスレッドですいません。
一番最初に言われている部分、同じ現象が私のところでもでました・・・。どうしてなのか・・・。負数は2で割ると問題があるのでしょうか?
どうしても、負の数で奇数にたどり着けません。absで行えば問題はないと思うのですが、ちょっと考え込んでしまい・・・意見を聞きたく。それとも、このコードが単純な部分で間違っていたら、アドバイス願います。


コード:

public void show1(){
Random ran1 = new Random();
int i1 = ran1.nextInt();
int flag1 = i1%2;
System.out.println(i1);

if(i1>=0){
if(flag1 == 0){
System.out.println("正:偶数");
}
if(flag1 == 1){
System.out.println("正:奇数");
}
}
else{
if(flag1 == -1){
System.out.println("負:奇数");
}
if(flag1 == 0){
System.out.println("負:偶数");
}
}
}




[ メッセージ編集済み 編集者: ぽん 編集日時 2003-12-12 12:12 ]

スキルアップ/キャリアアップ(JOB@IT)