• 位运算与优化


    基本概念


    真值:

    带符号位的机器数对应的真正数值称为机器数的真值
    0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

    原码:

    原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值
    PS:正数的原、反、补码都一样:0的原码跟反码都有两个,因为这里0被分为+0和-0。

    反码:

    正数的反码是其本身
    负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
    [+1] = [00000001]原 = [00000001]反
    [-1] = [10000001]原 = [11111110]反

    补码:

    正数的补码就是其本身

    负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

    [+1] = [00000001]原 = [00000001]反 = [00000001]补
    [-1] = [10000001]原 = [11111110]反 = [11111111]补

    PS:0的补码是唯一的,如果机器字长为8那么[0]补=00000000。

    移码:

    移码最简单了,不管正负数,只要将其补码的符号位取反即可。

    例如:X=-101011 , [X]原= 10101011 ,[X]反=11010100,[X]补=11010101,[X]移=01010101


    加法:

    减法:

    11 - 4 = 7

    原码                                补码正数的补码
    00001011 - 00000100 = 00001011 + 10000100 = 00001011 + 11111100 = 00000111 = 7 


    4 - 11 = -7

    原码 补码 负数的补码  补码反向
    00000100 - 00001011 = 00000100 + 10001011 = 00000100 + 11110101 = 11111001 = 10000111 = -7

    乘法:

    例子

    1101*11=1101*10+1101*1=11010+1101=100111


    0101*0110 = 101*(0*1000)+101*(1*100)+101*(1*10)+101*0

      = 101*(0*10*10*10)+101*(1*10*10)+101*(1*10)+101*0

      = 0+(101<<2)+(101<<1)+0

    最终乘法变成加法

    除法:


    除法变成减法进而转化成加法


    位运算符


    位操作符

    &:按位与
    |:按位或
    ^:按位异或(相同为1,不同为0)
    ~:取反()
    <<:左移
    >>:右移


    ~取反说明:

    以int a=5为例 ~a=-6

    过程

    计算机中的数以补码形式表示

    0000 0000 0000 0101           5的补码

    1111 1111 1111 1010           取反

    对补码再求补,得到原码

    1000 0000 0000 0101+0000 0000 0000 0001=

    1000 0000 0000 0110=-6

    跟位运算符相关的优化操作


    1操作int中的某一位

    取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1 
    将int型变量a的第k位清0,即a=a&~(1<<k) 
    将int型变量a的第k位置1, 即a=a|(1<<k) 
    将int型变量a的第k位取反, 即a=a^(1<<k) 

    2 取余操作

    对于x=2^n 的数取余可以用位操作代替   num%x = num&(x-1)

    3 不引入临时变量交换两个变量的值

    不引入第三变量,交换两个变量的值 (设 a=a1,b=b1) 
    目 标          操 作              操作后状态 
    a=a1^b1        a=a^b           a=a1^b1,b=b1 
    b=a1^b1^b1   b=a^b           a=a1^b1,b=a1 
    a=b1^a1^a1   a=a^b           a=b1,b=a1 

    4 取绝对值

    int abs(int x)
    {
    int y = 0;
    y = x>>31;          //x为负时y=-1
    return (x^y)-y;     //or: (x+y)^y
    }

    5 判断基偶 

    基数 x&1 = 1
    偶数 x&1 = 0

    6 整数的平均值 

    对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法: 
    int average(int x, int y)  //返回X,Y 的平均值 
    {    
        return (x&y)+((x^y)>>1); 
    }

    7 判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂 

    boolean power2(int x) 

        return ((x&(x-1))==0)&&(x!=0); 
    }  

    二进制补码运算公式: (抄来的备用)

    -x = ~x + 1 = ~(x-1) 
    ~x = -x-1 
    -(~x) = x+1 
    ~(-x) = x-1 
    x+y = x - ~y - 1 = (x|y)+(x&y) 
    x-y = x + ~y + 1 = (x|~y)-(~x&y) 
    x^y = (x|y)-(x&y) 
    x|y = (x&~y)+y 
    x&y = (~x|y)-~x 
    x==y:    ~(x-y|y-x) 
    x!=y:    x-y|y-x 
    x < y:    (x-y)^((x^y)&((x-y)^x)) 
    x <=y:    (x|~y)&((x^y)|~(y-x)) 
    x < y:    (~x&y)|((~x|y)&(x-y))//无符号x,y比较 
    x <=y:    (~x|y)&((x^y)|~(y-x))//无符号x,y比较

  • 相关阅读:
    [转]Delphi DLL的创建、静态 以及动态调用
    Delphi txt文件的操作(读取、写入)
    为什么要使用动态链接库(DLL)
    TStringGrid 实现下拉框
    Ryzen 4000'Vermeer' CPU和Radeon RX'Big Navi'图形卡
    AMD Ryzen 5000‘Cezanne’APU
    AMD–7nm “Rome”芯片SOC体系结构,支持64核
    ARM Cortex-M嵌入式C基础编程(下)
    ARM Cortex-M嵌入式C基础编程(上)
    基于ARM Cortex-M的SoC存储体系结构和实战
  • 原文地址:https://www.cnblogs.com/nafio/p/9137605.html
Copyright © 2020-2023  润新知