实现加法
https://www.jianshu.com/p/7bba031b11e7
https://blog.csdn.net/ojshilu/article/details/11179911
public class Arithmetic {
/**
* 两数之和
* 异或运算(^)得出的是和 sum
* 与运算(&)得出的是进位 carry
* 将sum和carry<<1继续相加即可
* @param a
* @param b
* @return
*/
public static int add(int a, int b){
if(b == 0) return a;
int sum = a ^ b;
int carry = (a & b) << 1;
return add(sum, carry);
}
/**
* 两数之差
* a - b实际上就是a + (-b)
* 在实际中做减法时,-b是用补码 取反 + 1
* @param a
* @param b
* @return
*/
public static int substract(int a, int b){
return add(a, negative(b));
}
/**
* 求一个数的相反数 取反再+1
* @param a
* @return
*/
public static int negative(int a){
return add(~a, 1);
}
/**
* 求一个数的符号,
* 0则为正数,否则就返回-1
* @param a
* @return
*/
public static int sign(int a){
return a >> 31;
}
/**
* 将数变为正数,如果数为正数,则为其本身,如果为负数,则变为其相反数
* @param a
* @return
*/
public static int positive(int a){
int flag = sign( a );
if(flag == 0) return a;
else return negative( a );
}
/**
* 两数乘积
* 先计算两个正数的乘积,然后符号最后加上
* 两个正数的乘积,a, b 就是 a 进行 b 次加法
* 注意最后加上符号
* @param a
* @param b
* @return
*/
public static int multiply(int a, int b){
boolean flag = sign(a) != sign(b);
a = positive( a );
b = positive( b );
int res = 0;
while(b > 0){
res = add(res, a);
b = substract( b, 1 );
}
if(flag){
return negative( res );
}
return res;
}
/**
* 两数之积
* 0101
* 0110
*
* 0000
* 0101
* 0101
* 0000
* 对应位置求和即可
*
* 根据 b 每一位为 1 就将 a 左移一位加到 res 上即可,为 0 就什么都不做
* @param a
* @param b
* @return
*/
public static int multiplay1(int a, int b){
boolean flag = (sign(a) != sign(b));
a = positive( a );
b = positive( b );
int res = 0;
while(b > 0){
if((b & 1) == 1){
res = add(res, a);
}
a = a << 1;
b = b >> 1;
}
if(flag) return negative( res );
return res;
}
/**
* 两数的商
* 用a - b,一直减,知道a < b时,此时减的次数就是商,a 就是余数
* 注意还有符号
* @param a
* @param b
* @return
*/
public static int divide(int a, int b){
if(b == 0) return -1;
boolean flag = (sign(a) != sign(b));
int res = 0;
a = positive( a );
b = positive( b );
while(a >= b){
res = add(res, 1);
a = substract( a, b );
}
if(flag){
return negative( res );
}
return res;
}
/**
* 两数之商
* 上面那种方法,每次都是减去一个 b,如果 b 太小的话,会计算的很慢
* 而如果以 b 的 2^i 倍开始减的话,如果 a 够减,则结果上加上 2 ^ i 倍
* 首先要判断 a 是否大于 b 的 2 ^ i倍
* 改为判断 a / (2 ^ i) 与 b 的大小,这样可以防止溢出
* a * (1 >> i) = a >> i
* (a >> i) >= b
* @param a
* @param b
* @return
*/
public static int divide1(int a, int b){
if(b == 0) return -1;
boolean flag = (sign( a ) != sign( b ));
a = positive( a );
b = positive( b );
int res = 0;
int i = 31;
while(i >= 0){
if((a >> i) >= b){
res = add( res, 1 << i );
a = substract( a, b << i );
}
i = substract( i, 1 );
}
if(flag) return negative( res );
return res;
}
public static void main(String[] args){
System.out.println(add( 7, 5 ));
System.out.println(substract( 7, 5 ));
System.out.println(negative(-33));
System.out.println(sign( -23 ));
System.out.println(positive( 3 ));
System.out.println(multiply( -7, -5 ));
System.out.println(divide( -35, -5 ));
System.out.println(divide1( -35, -5 ));
System.out.println(multiplay1( -7, 5 ));
}
}