首先我们想想位操作符-> ^ (异或)
异或可以相当于无进位相加
同时我们的进位为信息也可以用 (x & y)<<1来表示
那么我么的“+”可以相当于是无进位相加数 + 进位信息。
但是我们模拟实验“+”所以不能出现加号。
什么时候不需要加上进位信息--->进位信息为0的时候。
那么我们就可以知道,位运算实现“+”
public static int add(int a,int b){
int x = a>b ? a : b;
int y = x==a ? b : a;
int sum = 0;
while( y!=0 ){
sum = x ^ y;
y = (x & y)<<1;
x = sum;
}
return sum;
}
同时位运算实现减号---->就是
private static int negNum(int n){
return add(~n,1);
}
public static int minus(int x,int y){
return add(x,negNum(y));
}
将y--->进行取反+1就是-y.
x-y = x + (-y);
乘号
首先我们先想想我们是如何实现乘法的
我们先看这个20---。
首先20的第一个数字是0.那么我们用0乘以12所得为零。-------第一阶段结果为0。
其次20的第二个数字为2.那么我们是先将2*12,然后将所得的数字的后面加一个0,------第二阶段的结果为240.
那么我们可以想象,我们所进行的十进位的数字的乘法,实际上的步骤是:
将乘数的第0位数字,单独和被乘数相乘,相乘所得数向前移动0位,然后得到一个阶段的数字
将乘数的第1位数字,单独和被乘数相乘,相乘所得数向前移动1位,然后得到一个阶段的数字
将乘数的第2位数字,单独和被乘数相乘,相乘所得数向前移动2位,然后得到一个阶段的数字
将乘数的第3位数字,单独和被乘数相乘,相乘所得数向前移动3位,然后得到一个阶段的数字
...................
直到乘数的所有非零的数字都进行上诉运算后,然后将所有得到的阶段数字进行相加,就得到乘法所得到的数字。
但是当我们使用到二进制位也是如此。
public static int muli(int a,int b){
int sum = 0;
while(b != 0){
if((b & 1)!=0){
sum = add(sum,a);
}
a<<=1;
b>>>=1;
}
return sum;
}
接下来我们说说除法。
我们先了解一下我们平时是如何进行除法运算的。
首先我们十进制的除法运算,是首先从头开始
首先我们先从被除数中重头找到大于除数的数字,然后我们利用那么我们就能够算最大为几倍,然后相减。剩下的数字我们就继续找到,知道我们的被除数小于我们的除数的时候我们就得出结论
private static int div(int a,int b){
int x = isNeg(a) ? negNum(a) : a;
int y = isNeg(b) ? negNum(b) : b;
int res = 0;
for(int i = 30;i>=0; i = muli(i,1)){
if((x>>i)>=y){
res |= (1<<i);
x = minus(x, y<< i);
}
}
return isNeg(a) ^ isNeg(b) ? negNum(res) : res;
}
同时我们还是有一个问题需要我们来考虑,就是我们的这个类型是一个int类型的。当我们出现Integer.MIN_VALUE---->最小值的时候我们就没有办法转化成正数。那么我们就是需要特殊问题特殊处理了
1.除数和被除数都是Integer.MIN_VALUE----->直接返回1.
2.除数是Integer.MIN_VALUE,被除数不是。------>返回0.
3.除数不是,被除数是---->特殊情况特殊考虑。
4.除数和被除数都不是Integer.MIN_VALUE----->直接调用
特殊情况的讨论:
首先知道系统最小值是的绝对值比系统最大值的绝对值大1.
其次我们的Integer.MIN_VALUE--->无法转成正数,但是我们可以先将Integer.MIN_VALUE+1,这样就可以转成正数,同时我们算出来的余数在加上1,再进行一次除法计算,将两次得到结果相加就是我们特殊情况的处理
private static int div(int a,int b){
int x = isNeg(a) ? negNum(a) : a;
int y = isNeg(b) ? negNum(b) : b;
int res = 0;
for(int i = 30;i>=0; i = minus(i,1)){
if((x>>i)>=y){
res |= (1<<i);
x = minus(x, y<< i);
}
}
return isNeg(a) != isNeg(b) ? negNum(res) : res;
}
public static int divide(int a,int b){
if(a == Integer.MIN_VALUE && b==Integer.MIN_VALUE){
return 1;
}else if(b == Integer.MIN_VALUE){
return 0;
}else if(a == Integer.MIN_VALUE){
if(b == negNum(1)){
return Integer.MAX_VALUE;
}else{
int c = div(add(a,1),b);
return add(c,div(minus(a,muli(c,b)),b));
}
}else{
return div(a,b);
}
}
-------------------------------------------
public static int add(int a,int b){
int x = a>b ? a : b;
int y = x==a ? b : a;
int sum = 0;
while( y!=0 ){
sum = x ^ y;
y = (x & y)<<1;
x = sum;
}
return sum;
}
private static int negNum(int n){
return add(~n,1);
}
public static int minus(int x,int y){
return add(x,negNum(y));
}
public static int muli(int a,int b){
int sum = 0;
while(b != 0){
if((b & 1)!=0){
sum = add(sum,a);
}
a<<=1;
b>>>=1;
}
return sum;
}
private static boolean isNeg(int x){
return x<0;
}
private static int div(int a,int b){
int x = isNeg(a) ? negNum(a) : a;
int y = isNeg(b) ? negNum(b) : b;
int res = 0;
for(int i = 30;i>=0; i = minus(i,1)){
if((x>>i)>=y){
res |= (1<<i);
x = minus(x, y<< i);
}
}
return isNeg(a) != isNeg(b) ? negNum(res) : res;
}
public static int divide(int a,int b){
if(a == Integer.MIN_VALUE && b==Integer.MIN_VALUE){
return 1;
}else if(b == Integer.MIN_VALUE){
return 0;
}else if(a == Integer.MIN_VALUE){
if(b == negNum(1)){
return Integer.MAX_VALUE;
}else{
int c = div(add(a,1),b);
return add(c,div(minus(a,muli(c,b)),b));
}
}else{
return div(a,b);
}
}
private static int mod(int x,int y){
if((y & (minus(y,1)))==0){
return x & (minus(y,1));
}else{
for(int i = 30;i>=0; i = minus(i,1)){
if((x>>i)>=y){
x = minus(x,y<<i);
}
}
return x;
}
}