ビットマップ加算ビット演算は加算、減算、乗算、除算を実行します。
ビットマップが何であるかを簡単に説明しましょう
まず、データ処理を行う際にはデータを保存することが避けられないことが多く、その際にメモリを開放して配列を作成してデータを保存します。
しかし、int を例に挙げると、int は 4 バイトのスペースを占有します。
0 ~ 32 のデータを表したいとします。知っておく必要があるのは、1 バイトが 8 ビットであるということです。32 桁の数値を表すには整数を使用できます。表したいデータが 0 であるとします。-31、それなら形成外科でやればいいのに
より多くのデータを表現したい場合は、データを保存するための配列を作成でき、スペースを節約できます。
我们要是相要表示0-1023 那就是1024个数
1024/32=32 我们准备一个32长度的数组 我们就能表示1024个数
那么第一个数组里面的元素可以表示一下 我们的0-31之间有没有出现过数据
位图的功能就是可以做出一个集合
0-63 a%64===a&63
因为我们的一个num的数据其实是%64就是 获取到他们二进制的后7位
表現したいデータの範囲が 0 ~ 1023 であるとすると、数値は 1024 個あります。
1024/32=32 であれば、長さ 32 の配列を配置できます。
このように操作することで、実際に空間の複雑さを 32 分の 1 に大幅に削減できます。
1. ビットマップを作成する
public BitMap(int max) {
bits = new long[(max + 64) >> 6];//这里确定我们的大小是多大 确定我们的数据有多大
}
2. データを追加する
public void add(int num) {
//如何把170放到我们的数组里面去?
//num%64(这个就是获得)===num&63
//我们想办法将那个要放的数据的位置放置为1 代表这个数据进入了
//|=就是为了我们的数据是设置成为1 从而进行的操作进行处理
bits[num >> 6] |= (1L << (num & 63));//这一步就是把我们的数据设置成为1 代表出现过
//因为我们的二进制的位置就是 后7位就是我们的2进制的数据 但是其实上 我们的数据不止止是那些 我们只需要获取到我们的后七位就ok
まず第一に、私たちがしなければならない最初のステップは、170 がどこにあるかを見つけることです。まず、データが配置されている位置を見つけることができます。これは疑いの余地がありません。次に、特定の位置データを 1 に変更する必要があります。 1になる人
num&63====num%64 について簡単に説明しましょう
その理由は、データ &63 がある場合、その数値の 2 進数の最後の 7 桁はそのまま維持されるため、剰余の前のビットも 0 になり、最後の 7 桁だけがそのまま残るからです。予約、
では、なぜ %64 の代わりに &63 を使用する必要があるのでしょうか? これは、ビット操作の速度が通常の % 速度よりもはるかに速いためです。
データの追加の核心は、位置を決定する数値を 0 から 1 に変更することです。
では、データを削除するにはどうすればよいですか
まず最初に、その位置を見つけて 0 に変更する必要があります。
public void delete(int num) {
//如何删掉 就是把我们刚刚改成1的位置改成0就行了 我只管这一位 只要设置成为0就ok
bits[num >> 6] &= (~(1L << (num & 63)));
}
3. データが存在するかどうかを判断する方法
//我们可以先确定的是 我们要从哪个位置进行处理 然后说实话
public boolean contains(int num) {
return (bits[num >> 6] & (1L << (num & 63))) == 0 ? false : true;
}
これも処理されていますので、まず位置を判断して求めましょう、0なら存在しません、それ以外は存在します。
追加
ビット単位の演算を使用して加算を実装する方法
まず第一に、演算は a^b、つまりキャリーなしの加算であることを知る必要があります。
(a&b)<<1 これはキャリー情報を取得し、それら 2 つを加算するだけですが、演算処理中に加算は行われないので、キャリーがなくなるまで先ほどのアクションを繰り返す必要があることに注意してください。
public static int add(int a, int b) {
int sum = a;
while (b != 0) {
//当不存在进位的时候
sum = a ^ b;//这个结果就是我们的不进位相加
b = (a & b) << 1;//这个就是我们的进位的数据b->b'
a = sum;//a->a'
}
return sum;//返回我们的sum值就ok了
}
2. 減算をどのように達成するか? ?
b を -b に置き換えたら良くないでしょうか?
でも、私たちが来られないのを忘れてるでしょう - いいえ。
では、どのように操作すればよいのでしょうか? まず、少し常識を知っておく必要があります。
数値の負の値は ~a+1 に等しい
この数値がビット単位の否定に等しい場合、1 を追加すると OK になります。
まず、反対の数を見つける関数を書きます
public static int negNum(int n) {
return add(~n, 1);//一个数的负数等价于什么? 等价于我们的~n+1
}
減算機能が登場
public static int sub(int a, int b) {
return add(a, negNum(b));
}
乗算
まず、通常の 2 進直接乗算が次のとおりであることを確認しましょう。
混乱するかもしれませんが、パニックにならずに、段階的に説明していきます。
これは何を意味しますか? 最初に b データを観察します。データが 1 の場合は、a を変更せずに追加します。しかし、2 回目に追加すると、a は左に移動しようとします。ルールでは、次回も a は左に移動したいと考えます。ここに移動すると b は右に移動しますが、これは符号なしの移動になります。一度右に移動する必要があるため、右シフトが署名されていれば、サイクルは終わらない。
以下のコード
public static int mul(int a, int b) {
int res = 0;//这个代表我们的结果
while (b != 0) {
if ((b & 1) != 0) {
res = add(res, a);//
}
a <<= 1;//这个就是将我们的a向左移动
b >>>= 1;//这个就是将我们的b向右进行移动 获取它的下一位这个是用0来补 是因为>>>
}
return res;
}
分割
ここでは単純に除算処理を行うことができます
public static int divide(int a, int b) {
//但是注意一下就是我们的系统最小值是不能转化为我们的正数的其实是
// 我们只能转化为我们的不是系统最小值的数据 我们只能转化非系统最小值才行
int x = isNegative(a) ? negNum(a) : a;
int y = isNegative(b) ? negNum(b) : b;
int res = 0;
//是x/y
//011000
//000011
for (int i = 30; i >= 0; i = sub(i, 1)) {
//这个for循环也是遵循的是我们的减减的原则进行处理的
if ((x >> i) >= y) {
//你直接右移30位的话 就直接不可能大于我们的y就还不行 因为数据就直接溢出啦
res |= (1 << i);//这个就是让我们的数据变成1
x = sub(x, y << i);//然后我们的x就把b数据往左移动相应的位置
}
}
return isNegative(a) ^ isNegative(b) ? negNum(res) : res;//这里再次进行一次判断的处理如果说是负数的话
//我们就会进行的是负数的处理实现 实现我们的流程 如果不是的话 就会进行的是我们相反数的进行处理
}
私たちのアイデアについて話しましょう
a/b=c
c の値を取得するにはどうすればよいですか
a=1001
b=0010
c=?
まず a を右に移動して、いつ b より大きくなるかを確認します。
まず、30 ビットと 29 ビットを右に移動することを考えることができます。。。。。。
2ビット右にシフトすることがわかります
現時点でのデータは
そしてこの時点で b 画像を 2 ビット左に移動して処理することができます。
これはまさに逆のプロセスです
すると a は次のようになります
0001 このときどう動いても引き算は成功しません。
それで
c=0100
2番目のビットのみが1です
これで操作プロセスは終了です
これを実装するという考えは、最初に実行するプロセスは、データを使用してプロセスを改善する方法であるということです。
まず、データプロセスを示す具体的な例を挙げてみましょう。
仮説
b=00110
c=01110
a/b=c
すると、a=b×2 1+b×2 2+b×2^3
上記のインデックスを取得するためにデータを移動し続けるだけです。
結果データがどこにあるかを正確に判断するには
0
2番目のビットのみが1です
これで操作プロセスは終了です
これを実装するという考えは、最初に実行するプロセスは、データを使用してプロセスを改善する方法であるということです。
まず、データプロセスを示す具体的な例を挙げてみましょう。
仮説
b=00110
c=01110
a/b=c
すると、a=b×2 1+b×2 2+b×2^3
上記のインデックスを取得するためにデータを移動し続けるだけです。
結果データがどこにあるかを正確に判断するには