[算法]位运算问题之三(实现加减乘除)

题目:

给定32位整数a和b,可正、可负、可0,不能使用算术运算符,可分别实现a和b的加减乘除运算。

加法运算:

无进位相加:

a: 001010101
b: 000101111
a^b 001111010

只考虑进位:

a   001010101
b   000101111
(a&b)<<1 000001010

把完全不考虑进位的相加值与只与考虑进位的产生值再相加,就是最后的结果。重复这样的过程,直到进位产生的值完全消失,说明所有的过程都加完了。

public static int add(int a, int b) {
        int sum = a;
        while (b != 0) {
            sum = a ^ b;
            b = (a & b) << 1;
            a = sum;
        }
        return sum;
    }

减法运算:

实现a-b其实就是a+(-b),根据二进制在机器中表达的规则,得到一个数的相反数,就是这个数的二进制表达取反加1(补码)的结果。

public static int negNum(int n) {
        return add(~n, 1);
    }

    public static int minus(int a, int b) {
        return add(a, negNum(b));
    }

乘法运算:

res=a*20*b0+a*21*b1+…+a*2i*bi+…+a*231*b31,bi为0或1代表整数b的二进制数表达式中第i位的值。

public static int multi(int a, int b) {
        int res = 0;
        while (b != 0) {
            if ((b & 1) != 0) {
                res = add(res, a);
            }
            a <<= 1;
            b >>>= 1;
        }
        return res;
    }

除法运算:

b=res*a   ==>   a=b*20*res0+b*21*res1+…+b*2i*resi+…+b*231*res31

//判断是否为负
    public static boolean isNeg(int n) {
        return n < 0;
    }
    //相除的核心算法
    public 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 = 31; i > -1; 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 (b == 0) {
            throw new RuntimeException("divisor is 0");
        }
        //分子分母均为最小值
        if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {
            return 1;
        //分母为最小值,而分子不为最小值,返回0
        } else if (b == Integer.MIN_VALUE) {
            return 0;
        //分子为最小值,分母不为最小值
        } else if (a == Integer.MIN_VALUE) {
            int res = div(add(a, 1), b);
            return add(res, div(minus(a, multi(res, b)), b));
        } else {
            return div(a, b);
        }
    }
时间: 2024-10-05 13:03:07

[算法]位运算问题之三(实现加减乘除)的相关文章

java加密解密算法位运算

一.实例说明 本实例通过位运算的异或运算符 “ ^ ” 把字符串与一个指定的值进行异或运算,从而改变每个字符串中字符的值,这样就可以得到一个加密后的字符串.当把加密后的字符串作为程序输入内容,异或运算会把加密后的字符串还原为原有字符串的值.效果图如下: 二.实现过程 1 package com.itxxz; 2 3 import java.util.Scanner; 4 5 /** 6 * java加密解密算法 7 * 8 * @author 螃蟹 9 * 网站:IT学习者 10 * 网址:ht

用位运算实现四则运算之加减乘除(用位运算求一个数的1/3) via Hackbuteer1

转自:http://blog.csdn.net/hackbuteer1/article/details/7390093 ^: 按位异或:&:按位与: | :按位或 计算机系统中,数值一律用补码来表示:因为补码可以使符号位和数值位统一处理,同时可以使减法按照加法来处理. 对补码做简单介绍:数值编码分为原码,反码,补码,符号位均为0正1负. 原码 -> 补码: 数值位取反加1 补码 -> 原码: 对该补码的数值位继续 取反加1 补码 的绝对值(称为真值):正数的真值就是本身,负数的真值是各

Apriori算法-位运算-C语言

原文地址:http://blog.csdn.net/liema2000/article/details/6118423 ///////////////////////////////////////////////////////////////////////////** 文件名称:FAST apriori.cpp * 摘 要:采用位运算提高算法的效率 * 将每一项抽象为数值,通过与运算判断是否存在,abcde为16,8,4,2,1换成2进制,各占一个位置,互相不干扰.局限于字母.换算的比较字

数据结构与算法-位运算

位运算位运算是把数字用二进制表示之后,对每一位上的0或者1的运算.理解位运算的第一步是理解二进制.二进制是指数字每一位都是0或者1,如十进制的2转换为二进制之后是10,而十进制的10转换为二进制之后是1010.在程序员圈子里有一个流传了很久的笑话,说世界上有10种人,一种人知道二进制,另一种人不知道二进制. 下面是几个常见的关于位运算的算法题:基本位运算位运算总共只有5种运算:与&,或|,异或^,左移<<,右移>>.与,或,异或的运算规则: 左移,右移运算规则:左移运算m

算法——位运算

&:按位与. |  :按位或. ~ :按位取反,带符号位.(注意和!的区别,!只是逻辑取反)  ^ : 异或也叫半加运算:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0. >> : 表示右移,算数右移,如果该数为正,高位补符. >>>:表示无符号右移,也叫逻辑右移,高位补零. 小操作: 1. 判断奇偶数 a & 1 2. 交换变量 a ^= b, b ^= a, a ^= b 3. 乘以(除以)2的n次方:左移,右移:取模运算:a % (2 ^ n) 等价于

[算法]位运算问题之一

一.不用额外变量交换两个整数的值 a=a^b; b=a^b; a=a^b; 或者: a=a+b; b=a-b; a=a-b; 二.不同任何比较判断找出两个数中较大 有两种方法,方法一有一定的局限性,a-b的值可能溢出,这样溢出后符号改变,返回结果就不正确. 而方法二对a和b是否异号进行了判断,如果同号,则按照方法一返回,否则直接返回正的数就行. a-b的值如果为0的处理按照大于0处理. //如果n为1,则返回0:如果n为0,则返回1 public static int flip(int n) {

[算法]位运算之二

题目一: 给定一个整形数组arr和一个大于1的整数k.已知arr中只有1个数出现了奇数次,其他的数都出现了偶数次,请返回出现了奇数次的数. 时间复杂度为O(N),额外空间复杂度为O(1). 思路: 整数n与0异或的结果是n,整数n与整数n异或的结果是0.所以先申请一个整形变量,记为eO.把eO和每个数异或(eO=eO^当前数),最后eO的值就是出现了奇数次的那个数. 异或运算满足交换律和结合律. public static void printOddTimesNum1(int[] arr) {

[算法]位运算实现加减法

异或可以实现不考虑进位的加法,相同为0,不同为1 0101 ^ 0001 = 0100 两个数相加不考虑进位从二进制角度上说就是相同为0,不同为1,因为二进制只有两个数1和0 1+1=0 0+1=1 与运算可以实现进位 同为1才为1 0101 & 0001 = 0001 说明最低位有进位 int add(int a, int b) { return b == 0 ? a : add(a ^ b, (a & b) << 1); } 左移一位表示 将进位加到前一位 递归表示要遍历进

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始