この記事では、第二である「面白いビットコンピューティングのための記事」第二の物品。
我々は、コンピュータ装置の基本的な動作は、バイト(バイト)であることを知って、バイトは8ビット(ビット)の組成物から構成され、唯一の高および低、実際には、すなわち、ビット1または0を記憶することができます。どんなに複雑なロジック、最終的にはコンピュータの底面に反映大きなデータ、クールなインターフェイスは、ストレージとコンピューティングの0101のためだけではありません。そのため、コンピュータの動作の基本的な原理の理解を改善するために、ビット・コンピューティングのヘルプを理解します。
まず、ほか
二つのバイナリXOR演算の結果は、キャリービットを考慮せずに到達し、
二つの二進AND演算結果がビット1に含まれるキャリービットです。
0101 + 0001 = 0110
次のように例:
//计算 0101 + 0001
0101 ^ 0001 = 0100 //异或结果表明,如果不考虑进位,那么结果为0100
0101 & 0001 = 0001 //与运算结果表明,最低位需要向次低位进1
0001 << 1 = 0010 //与运算结果左移一位,将进位加到高位上
//递归计算 0100 + 0010,直到+号右侧数字为0
Javaコード:
再帰
public static int add(int a, int b) {
if (b == 0) {
return a;
} else {
return add(a ^ b, (a & b) << 1);
}
}
循環
public static int add2(int a, int b) {
int sum = a;
while (b != 0) {
sum = a ^ b;
b = (a & b) << 1;
a = sum;
}
return sum;
}
第二に、減算
同じアイデアや追加が、その数に加え、反対の数と同じ数のマイナス。
例えば:5 + 5-1 =( - 1)。そこで、我々は単に被減数とは反対の番号が必要です。
どのように反対の数の数を見つけるには?
同じ元のコードの正の補数と、元のコードシンボルに加えて、負の数を補完反転メンバー、次いで一つ最後のビット、コンピュータの補数形式で格納されます。
例えば:
コンピュータのバイナリでは1として表される:0000 0001
等のコンピュータで表現-1バイナリ:11111111
計算は次のとおりです。
-1オリジナルコード:10000001
反転-1:1111 1110
補完-1:1111 1111
請求項1は、元のコード(0000 0001)である反転-1を得るために、(11111110)に反転させることができます
要約、反対の数の数は、すべての否定を見つけるための方法の数、最後の1を加えたものです。
Javaコード:
public static int minus(int a, int b) {
return add(a, add(~b, 1));
}
第三に、乗算
思考がなければ、紙書かれた計算上のバイナリプロセスを掛けることができます。
0101 a
× 0110 b
----------------
0000
0101
0101
+ 0000
----------------
00011110
書き込まれた計算バイナリ乗算をカーディング:
初期化乗算結果が0、最後のビット、ディジタルB 0→1→1→0を、横断している最後のビットが共に0、すなわち同じ製品、左0、乗算結果である場合;場合の最後のビット1、A、Aと一緒に乗算結果と、左1。
それBデジタル最後のビットを行き来するには?
先に学んだ、我々は運用最後のビットの数を取ることができ、およびB番号は、変位の終わりに、== 0 Bナンバーまで、右にシフト。
ここでは、正と負の符号の問題の数は、2つの数のB、そして最後にその符号の絶対値の積を計算することであることに注意してください。
Javaコード:
public static int multiply(int a, int b) {
//将乘数和被乘数都取绝对值
int A = a < 0 ? add(~a, 1) : a;
int B = b < 0 ? add(~b, 1) : b;
//计算绝对值的乘积
int P = 0;
while (B != 0) {
if ((B & 1) != 0) { //取乘数的二进制的最后一位,0 or 1
P = add(P, A);
}
A = A << 1;
B = B >> 1;
}
//计算乘积的符号
if ((a ^ b) < 0) {
P = add(~P, 1);
}
return P;
}
第四に、除算
達成するための最も簡単な部門は、配当金が除数より小さくなるまで、この時点での数は、当社が事業を縮小する必要があるということですが、今回は配当金は余りあり、配当を切断するために使用除数を維持することです。
唯一の注意点は、残りのプロバイダのシンボルとサインです。シンボルのも同じ番号が正、負の符号が反対である、つまり、道の乗算が同じであるかを決定します。被除数の残りの符号及び記号は同じです。
そして、単純な乗算は、我々は最初の2つの数の商の絶対値の、残りを見つけなければならない、などここで、実現しました。最後に、シンボルを決定します。
public static int[] divide(int a, int b) {
//对被除数和除数取绝对值
int A = a < 0 ? add(~a, 1) : a;
int B = b < 0 ? add(~b, 1) : b;
//对被除数和除数的绝对值求商
int C = A; // 余数C
int N = 0; // 商N
while (C >= B) {
C = minus(C, B); // C-B
N = add(N, 1); // N+1
}
// 求商的符号
if ((a ^ b) < 0) {
N = add(~N, 1);
}
// 求余数的符合
if (a < 0) {
C = add(~C, 1);
}
return new int[]{N, C};
}
最適化アルゴリズムは、whileループ、それの数を削減することをどのように、その大きなA、Bマイナーな例では、このアルゴリズムが非効率的に注意すべき?
考えることは困難ではない、除算の乗算のプロセスが後方に来ます。例えば9÷4 = 2 ... 2 * 4 + 1 = 9です。1が4未満であるため、4 * 2 9に保存すると仮定、結果は、1に等しくてもよく、余りが1である、9÷4が2で商業的に入手することができます。
4の倍数を決定するためにどのように最終結果に近づいための鍵です。我々は、知っている32ビット整数をINT、最初の符号ビットを示すことに加えて、[2 ^ 0 ^ 1 2、^ 2 2、2 ^ 30]の各ビットの大きさは、最大2 ^ INT 31の整数です。 -1。したがって、我々は彼らの製品は、除数、除数意志それ減算、およびよりも大きい場合、1を乗じた配当2 ^ 31 ^ 30 2、^ 3 2 ...、^ 2 2、2 ^ 1に変えることができますループの終わりまで除数として機能し続ける差し引いた余り。
Javaコード:
public static int[] divide(int a, int b) {
// 对被除数和除数取绝对值
int A = a < 0 ? add(~a, 1) : a;
int B = b < 0 ? add(~b, 1) : b;
int N = 0; // 商 N
for (int i = 31; i >= 0; i--) {
// 未使用A>=(B<<i)进行判断,因为只有左移B时舍弃的高位不包含1,才相当于该数乘以2的i次方.
if ((A >> i) >= B) { // A ÷ 2^i >= B
N += (1 << i); // N = N + 2^i
A -= (B << i); // A = A - B*2^i
}
}
int C = A; // 余数C
// 求商的符号
if ((a ^ b) < 0) {
N = add(~N, 1);
}
// 求余数的符号
if (a < 0) {
C = add(~C, 1);
}
return new int[]{N, C};
}