面白いのは位置によって操作します。
3247 ワード
いくつかの面白いビット操作の書き方を見ました。
1.大体変更しました。分かりやすいように、パラメータはint型であり、65536以上であり、このint型の10桁とビットを返します。
2.これは65536より小さい整数を計算したもので、桁数はいくらですか?
特に
(i*52429)>>19=i/10
原理:52429/2^19=0.1 000038146972656だから(i*52429)>>19=i*0.1
注意: 2^10=1024、103/1024=0.1005859375
2^11=2048、205/2048=0.1009765625
2^12=4096、410/4096=0.1009765625
2^13=8192,820/8192=0.1009765625
2^14=16384、1639/16384=0.1003662109375
2^15=32768,3277/32768=0.1 00061035125
2^16=65536,6554/65536=0.1 0006103515625
2^17=1313131307、1318/131313712=0.1 00061035125
2^18=262144,26215/262144=0.10002288835938
2^19=524288、52429/524288=0.1 000038146972656
精度19が最高で、20*iを超えるとオーバーフローします。
その後:(i+(i<<2)+(i<<3)+(i<<6)+(i<<7)+(i<<10)+(i<<11)+(i<<14)+(i<<15)>>19=i/10
以上の二つの例はジェームズコードで見られます。また、JDK内のInteger類で見られます。 static void get Chars(int i,int index,char[]buf)にもあります。jedisの作者はJDKのソースコードに対して真剣に読んでいるようです。
3.正の整数から上に最も近い2つの二乗を求めます。
例えば232をバイナリで表現すると0000000 11101000です。一番近いバイナリは
0000000 000001,11111+1
上の理論によって、このコードはもう一歩ずつこの数を1にして、+1にします。
232を例にとると、4バイトとは書きません。
232=11101000
1)1110 1000>>1/イコール0111 0100は、必ず最高1位の次の位を1に変えます。 1110,000|0111/0100/1111 1100に等しいと最高の二人は1になります。
2)1111 1100>>2/0011 1111に等しいということは、赤の二桁を1 1111 1111/1111にすることです。
3)
1111>>4/イコール0000 1111 は、ビーコンの4桁を1 1111の1240万1111/1111に変更することと同じです。 最上位の1バイトを1にするのに相当します。
4)実は最高の2バイトを1にします。
5)int 4バイトを全部1にする
以上のように、全体のint型数の一番高い1位以下が全部1になり、最後に1を加えると全体のテクニックが完成し、結果が返ってきます。
1.大体変更しました。分かりやすいように、パラメータはint型であり、65536以上であり、このint型の10桁とビットを返します。
public static int getTenAndOne(int value){
if (value < 0) {
throw new RuntimeException(" ");
}
int q = value / 100;
int result = value - ((q << 6) + (q << 5) + (q << 2));
return result;
}
は通常私達が一つの数の後二桁を計算する時、int result=value%100を使っていますが、ここはそうではありません。JAVAは%の演算子の時、実際にint result=value-value/100*100という本を読んだ覚えがあります。上の方法を見てみたら、これと似ています。こう見ても((q << 6) + (q << 5) + (q << 2))
この操作は実は(a/100)*100の操作ですが、シフトはどうやって*100になりますか?かつての基本書では*2を左に移動しますので、上の式を整理するとq*2^6+q*2^2=q*(2^6+2^5+2^2)=q*100です。えっと、…。実はこれを知りたいと思った時、また感嘆しました。どこにでもいる数学です。2.これは65536より小さい整数を計算したもので、桁数はいくらですか?
pulic static int getOne(int value){
if(value<0||value>=65536){
throw new RuntimeException(" ");
}
int q = (value * 52429) >>> 19;
int result = value - ((q << 3) + (q << 1));
return result;
}
例1の中の経験によって、分かりやすくなりますが、実はこの例はレスリング=value-value/10*10です。特に
int result = value - ((q << 3) + (q << 1));
分かりやすいのはvalue-(q*2^3+q*^2)=value-q*(8+2)=value-q*10です。上の言葉はvalue/10という意味ですが、簡単なvalue/10はどうして52429をかけて右に19桁も移動しますか?googleの説明も勉強になりました。(i*52429)>>19=i/10
原理:52429/2^19=0.1 000038146972656だから(i*52429)>>19=i*0.1
注意: 2^10=1024、103/1024=0.1005859375
2^11=2048、205/2048=0.1009765625
2^12=4096、410/4096=0.1009765625
2^13=8192,820/8192=0.1009765625
2^14=16384、1639/16384=0.1003662109375
2^15=32768,3277/32768=0.1 00061035125
2^16=65536,6554/65536=0.1 0006103515625
2^17=1313131307、1318/131313712=0.1 00061035125
2^18=262144,26215/262144=0.10002288835938
2^19=524288、52429/524288=0.1 000038146972656
精度19が最高で、20*iを超えるとオーバーフローします。
その後:(i+(i<<2)+(i<<3)+(i<<6)+(i<<7)+(i<<10)+(i<<11)+(i<<14)+(i<<15)>>19=i/10
以上の二つの例はジェームズコードで見られます。また、JDK内のInteger類で見られます。 static void get Chars(int i,int index,char[]buf)にもあります。jedisの作者はJDKのソースコードに対して真剣に読んでいるようです。
3.正の整数から上に最も近い2つの二乗を求めます。
public static int nextPowerOfTwo (int value) {
if (value == 0) {
return 1;
}
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
}
実は1つの整数を求めて一番近い2の乗がこの整数の左から1番目以下のすべての位が1になって、もう1つプラスします。例えば232をバイナリで表現すると0000000 11101000です。一番近いバイナリは
0000000 000001,11111+1
上の理論によって、このコードはもう一歩ずつこの数を1にして、+1にします。
232を例にとると、4バイトとは書きません。
232=11101000
1)1110 1000>>1/イコール0111 0100は、必ず最高1位の次の位を1に変えます。 1110,000|0111/0100/1111 1100に等しいと最高の二人は1になります。
2)1111 1100>>2/0011 1111に等しいということは、赤の二桁を1 1111 1111/1111にすることです。
3)
1111>>4/イコール0000 1111 は、ビーコンの4桁を1 1111の1240万1111/1111に変更することと同じです。 最上位の1バイトを1にするのに相当します。
4)実は最高の2バイトを1にします。
5)int 4バイトを全部1にする
以上のように、全体のint型数の一番高い1位以下が全部1になり、最後に1を加えると全体のテクニックが完成し、結果が返ってきます。