数据结构--只用位运算实现加减乘除操作
实现加法
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 )); } }