位运算的操作(加减乘除、负数、乘方、1的个数)

一、位运算相关规律+口诀

c++中的位运算相关规律总结和口诀

二、加减乘除

int add(int num1, int num2){ 
	int temp;
    do {
    	temp = num1 ^ num2;//不进位相加:异或
    	num2 = (num1 & num2) << 1;//进位:位与+左移
    	num1 = temp;
    } while(num2!=0);
    return num1;
}
//num1为被减数,num2为减数
int substract(int num1, int num2){
    int subtractor = add(~num2, 1);//负数:取反加1
    int result = add(num1, subtractor);  
    return result ;
}
1、1110&1,最后1位=0,所以结果=0;被乘数1101左移1位=11010,乘数1110右移1位=0111;
2、0111&1,最后1位=1,所以结果=11010;被乘数11010左移1位=110100,乘数0111右移1位=0011;
3、0011&1,最后1位=1,所以结果=11010+110100=1001110;被乘数110100左移1位=1101000,乘数0011右移1位=0001;
4、0001&1,最后1位=1,所以结果=1001110+1101000=10110110;被乘数110100左移1位=11010000,乘数0011右移1位=0
乘数=0,循环结束。
(1) 判断乘数是否为0,为0跳转至步骤(4)
(2) 将乘数与1作与运算,确定末尾位为1还是为0,如果为1,则相加数为当前被乘数;如果为0,则相加数为0;将相加数加到最终结果中
(3) 被乘数左移一位,乘数右移一位;回到步骤(1)
(4) 确定符号位,输出结果;
//multiplicand被乘数,multiplier乘数,product乘积
int multiply(int a, int b) {  
    //将乘数和被乘数都取绝对值 
    int multiplicand = a < 0 ? add(~a, 1) : a;   
    int multiplier = b < 0 ? add(~b , 1) : b;  
     
    //计算绝对值的乘积  
    int product = 0;  
    while(multiplier > 0) {    
        if((multiplier & 0x1) > 0) {// 每次考察乘数的最后一位    
            product = add(product, multiplicand);    
        }     
        multiplicand = multiplicand << 1;// 每运算一次,被乘数要左移一位    
        multiplier = multiplier >> 1;// 每运算一次,乘数要右移一位(可对照上图理解)  
    }   
    //计算乘积的符号  
    if((a ^ b) < 0) {    
        product = add(~product, 1);  
    }   
    return product;
}

 

计算机是一个二元的世界,所有的int型数据都可以用[2^0, 21,...,231]这样一组基来表示(int型最高31位)。不难想到用除数的231,230,...,22,21,2^0倍尝试去减被除数,如果减得动,则把相应的倍数加到商中;如果减不动,则依次尝试更小的倍数。这样就可以快速逼近最终的结果。2的i次方其实就相当于左移i位,为什么从31位开始呢?因为int型数据最大值就是2^31

//dividend被除数,divisor除数,quotient商,remainder余数
int divide_v2(int a,int b) {   
    // 先取被除数和除数的绝对值    
    int dividend = a > 0 ? a : add(~a, 1);    
    int divisor = b > 0 ? a : add(~b, 1);    
    int quotient = 0;// 商    
    int remainder = 0;// 余数    
    for(int i = 31; i >= 0; i--) {
        //比较dividend是否大于divisor的(1<<i)次方,不要将dividend与(divisor<<i)比较,而是用(dividend>>i)与divisor比较,
        //效果一样,但是可以避免因(divisor<<i)操作可能导致的溢出,如果溢出则会可能dividend本身小于divisor,但是溢出导致dividend大于divisor       
        if((dividend >> i) >= divisor) {            
            quotient = add(quotient, 1 << i);            
            dividend = substract(dividend, divisor << i);        
        }    
    }    
    // 确定商的符号    
    if((a ^ b) < 0){
        // 如果除数和被除数异号,则商为负数        
        quotient = add(~quotient, 1);    
    }    
    // 确定余数符号    
    remainder = b > 0 ? dividend : add(~dividend, 1);    
    return quotient;// 返回商
}

三、判断整数number是否是2的乘方

bool isPower(int number) {
	return (number & number - 1) == 0;
}

四、判断正整数转换成二进制后的数字“1”的个数

//乘方:n&(n-1)可以把整数二进制的最右边的数由1变为0 
int bitCount1(int n) {
	int count = 0;
	while (n != 0) {
	    n = n & (n - 1);
	    count++;
	}
	return count;
}

//移位: 二进制与1进行&运算的时候,当最末位也就是最右边的一位为1的时候,结果就是1,
//判断完最后一位,然后把整数的二进制右移一位,再判断,直到整数等于 0 结束循环
int bitCount2(int n) {
	int count = 0;
	while (n > 0) {
	    if ((n & 1) == 1) count++;//如果最右边的值是1
	    n >>= 1; //向右一位
	}
	return count;
}

//可忽略。分治法,详见:https://www.jianshu.com/p/d8a0c6299dab
int bitCount3(int i) {
	i = i - ((i>>>1) & 0x55555555);
	i = (i & 0x33333333) + ((i>>>2)&0x33333333);
	i = (i+(i>>>4)) & 0x0f0f0f0f;
	i = i + (i>>>8);
	i = i + (i>>>16);
	return i & 0x3f;
}

转载:加减乘除

判断一个整数是否是2的乘方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值