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

      

  • 相关阅读:
    SharePoint 2013 中的 URL 和标记
    负载均衡
    高可用集群
    客户端访问浏览器的流程
    【SDOI2014】数表
    【UR #5】怎样跑得更快
    【BZOJ2820】YY的GCD
    【SDOI2017】数字表格
    Codeforces 548E Mike ans Foam (与质数相关的容斥多半会用到莫比乌斯函数)
    【BZOJ2693】jzptab
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/9013128.html
Copyright © 2011-2022 走看看