zoukankan      html  css  js  c++  java
  • 位运算复习

    前言

    首先向 学长Luckblock谢罪自己位运算没学好/kk

    话说考场推错位运算的公式就……关键自己试了不少样例居然都过了……
    现在回顾学长的讲课内容
    文章内容选自
    学长博客
    MosumLucifer博客

    比特B(bit)

    1GB = 1024MB = 1024^2 KB = 1024^3 Bit
    Bit 指二进制中的一个 2 进制位,是信息的最小单位。
    只包含 0/1 两种状态。
    对应着内存条中的通电/断电。

    关于变量

    变量是内存中开辟的,一段用于储存数据的空间。
    一个 int,32 个比特,32 个 2 进制位。
    一个 char,8 个比特,8 个 2 进制位。
    将一个变量内所有比特存储的数顺次排列,看成一个2进制数。即为变量存储的值。
    负数是通过补码来完成的取反后+1:一个变量的第一个 2 进制位设为符号位,第一个 2 进制位为 0 表示正数,为 1 则表示负数。这样的表示法称为补码。

    ull

    扔去最高的符号位 不能表示负数

    位运算

    直接对补码进行操作
    位运算符号
    位运算

    add:

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

    清晰的写法(好吧上面的写法是由下面的推出来的):

    int add(int x,int y){
    	return ((x&y)<<1)+(x^y); 
    } 
    

    加法与减法同理,减去一个正数等于加上一个负数,负数二进制位补码(取反+1)那么就可以直接加它的相反数

    subtrack

    int subtrack(int x,int y){
    	int subtractor = add(~y,1);
    	return add(x,subtractor);
    } 
    

    效率提高的位运算计算方式

    multiply

    1. 将乘法转换成加法:效率低下显然的做法略过
    2. 更正算法
      (1) 判断乘数是否为0,为0跳转至步骤(4)
      (2) 将乘数与1作与运算,确定末尾位为1还是为0,如果为1,则相加数为当前被乘数;如果为0,则相加数为0;将相加数加到最终结果中;
      (3) 被乘数左移一位,乘数右移一位;回到步骤(1)
      (4) 确定符号位,输出结果;
    int multiply (int x, int y){
    	int multiplicand = x < 0 ? add(~x,1) : x;
    	int multiplier = y < 0 ? add(~y,1) : y;
    	int product = 0;
    	while(multiplier > 0) {
    		if((multiplier & 1) > 0) {
    			protuct = add(protcut ,multiplicand);
    		}
    		multiplicand <<= 1;
    		multiplier >>= 1;
    	}
    	if((a ^b) < 0){
    		product = add(~product,1);
    	}
    	return product ;
    }
    

    4. 除法运算

    除法运算很容易想到可以转换成减法运算,即不停的用除数去减被除数,直到被除数小于除数时,此时所减的次数就是我们需要的商,而此时的被除数就是余数。这里需要注意的是符号的确定,商的符号和乘法运算中乘积的符号确定一样,即取决于除数和被除数,同号为证,异号为负;余数的符号和被除数一样。同样的效率低下
    由于每一个数都可以又(2^i)来表示出来那就可以用(2^i)来逐步尝试减去被除数,相应的倍数加入商中,减不动就用更下的(i)
    如此可以快速求得答案

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

    注意位运算尽可能加括号……运算优先级太低了

    快速幂(由每个数可以拆成(2^i)的加和得到)

    ll quicklypow(ll x, ll y ,ll mod){
    	ll ans = 1;
    	for(;y;y >> =1) {
    		if(y&1) ans = ans * x % mod;
    		x = x * x % mod; 
    	}
    	return ans;
    } 
    

    大整数带模乘法(大魔法)

    由乘法分配率知(x(a+b) = x * a + x * b)
    将y拆成二进制的数,类比快速幂

    ll quickly(ll x, ll y, ll mod){
    	ll ans =  0;
    	for(; y; y >>=1) {
    		if(y&1) ans = (ans + x) % mod;
    		x = (x * x ) % mod;
    	}
    	return ans;
    }
    

    状压:

    把 int 当长度为 32 的 bool 数组用。
    右侧数第 1 个二进制位位称为第 0 位。
    状态处理

    后记

    对位运算处理的理解加深,计算机对位运算的使用理解透了,一些用到位运算的公式题也就会推导了
    ps:有错误希望指正啊

  • 相关阅读:
    jmetal随机数
    [转]IDEA断点调试基础
    [转]java指数表示最大数和最小数
    反向学习相对基学习opposition-based learning简介
    IGD反转世代距离-多目标优化评价指标概念及实现
    matlab sum函数
    多目标优化拥挤距离计算
    [转]matlab 中的波浪号
    多目标优化按支配关系分层实现
    Matlab矩阵加入新元素
  • 原文地址:https://www.cnblogs.com/-wzd233/p/13921141.html
Copyright © 2011-2022 走看看