zoukankan      html  css  js  c++  java
  • 数据结构--只用位运算实现加减乘除操作

    实现加法

    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 ));
        }
    }
    

      

  • 相关阅读:
    HDU 5912 Fraction (模拟)
    CodeForces 722C Destroying Array (并查集)
    CodeForces 722B Verse Pattern (水题)
    CodeForces 722A Broken Clock (水题)
    CodeForces 723D Lakes in Berland (dfs搜索)
    CodeForces 723C Polycarp at the Radio (题意题+暴力)
    CodeForces 723B Text Document Analysis (水题模拟)
    CodeForces 723A The New Year: Meeting Friends (水题)
    hdu 1258
    hdu 2266 dfs+1258
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/9013128.html
Copyright © 2011-2022 走看看