位运算

作者: 晓晓桑 | 来源:发表于2020-04-23 21:17 被阅读0次

16进制 地址形式
0 1 2 4 5 6 7 8 9 A B C D E F
F是15
0x:16进制标志
2进制:内存存储数据
0 1

进制转换

1.基数相加法
2.反转取余法
这两种方法都能单独转,但是为了计算方便,一般是
10进制转其他进制:反转取余法
其他进制转10进制:基数相加法

1.基数相加法
  • 0XAB2 ->10进制数
    各个位上的数乘他的基数 比如十进制1234 = 4 * 10^0 + 3 * 10^ 1+2 * 10^2 + 4* 1^3
    那么0XAB2=2* 16^0+ B* 16^ 1+A* 16^2 (B=11,A=10)
  • 八进制7235 ->10进制数
    5* 8^0 + 3* 8^1+ 2 *8^2 +7 *8^3
  • 0XAB2 -> 8进制数
    分析:十六进制转10进制:0XAB2=2* 16^0+ B* 16^ 1+A* 16^2 (B=11,A=10)
    转8进制,就不乘以16的n次方了,因为16在8进制里是20,所以,乘20的n次方。
    B是八进制的13,A是八进制的12
    如下:
    0XAB2=2* 20^0+ 13* 20^ 1+12* 20^2
2.反转取余法

转几进制就除以几
234 转成8进制:


image.png
3.进制互相转换
image.png

16-2


image.png

2-16


image.png

位操作

位操作的两种方式:位运算符、位字段
注意:位运算只支持整数

  • ~:按位取反
    一个数的二进制的0、1交换
    &:按位与
    |:按位或
    ^:按位异或
    <<和>> :移位运算符
    &=、|=、^=、>>=、<<=

~:按位取反

正数:补码是本身
负数:补码:数据位按位取反再加1(符号不变)
注意⚠️:最高位是符号位,不参与按位取反加一中的取反

#include "c3.h"
int main(int argc, char *argv[]) {

    //分析:
    //整数按照补码形式进行存储的
    //正数的补码是本身,负数的数据位补码是按位取反再加1
    //负数最高位存储是1,正式最高位存储是0
    //-123二进制是:1(符号位) 111 1011 ,按位取反加1:1(符号位不变)000 0100,
    // 再加1,1000 0101,也就是-123在内存中存储的数据。
    //b的话就是a的存取取反:即1000 0101取反0111 1010
    // 0111 1010:122
    char a = -123;
    char b = ~a;
    printf("%d\n", b);//122

    // --------------------
    //123在内存中的存储是:0(符号位) 111 1011
    //取反得到b:1 000 0100
    //b的存储数据是1 000 0100,那么10进制数就是:先-1,再按位取反
    //即:1 000 0011,再按位取反:0 0111 1100:即124,符号位是0 则是-124
    char c = 123;
    char d = ~c;
    printf("%d\n", d);//-124
    return 0;
}

&:按位与

只有1&1 =1,
其他都是0
1010 1111&1100 1010
得:1000 1010

#include "c3.h"

int main(int argc, char *argv[]) {

    //分析:79的二进制:0 100 1111 ,-23的二进制:1 001 0111
    //-23在内存中存取数据是:数据位按位取反+1 :1 110 1001
    //0 100 1111 & 1 110 1001 得 0 100 1001 得:+73
    char a = 79;
    char b = -23;
    char c = a & b;
    printf("%d\n", c);//73
    return 0;
}

|:按位或

只有0|0得0,
其他都是1
1010 1111 | 1100 1010
得:1110 1111

#include "c3.h"

int main(int argc, char *argv[]) {

    //分析:79的二进制:0 100 1111 ,-23的二进制:1 001 0111
    //-23在内存中存取数据是:数据位按位取反+1 :1 110 1001
    //0 100 1111 | 1 110 1001 得 1 110 1111
    // 因为上面存储的数据是负数,所以得到真正的数据:-1 按位取反
    //即:1 0110 1110 取反:1 0001 0001,即-17
    char a = 79;
    char b = -23;
    char c = a | b;
    printf("%d\n", c);//-17
  
    return 0;
}

^:按位异或

不同为1,
相同为0
1010 1111 ^ 1100 1010
得:0110 0101
注意:C中pow是平方,sqrt是开方

#include "c3.h"

int main(int argc, char *argv[]) {

    //分析:79的二进制:0 100 1111 ,-23的二进制:1 001 0111
    //-23在内存中存取数据是:数据位按位取反+1 :1 110 1001
    //0 100 1111 ^ 
      1 110 1001 得 1010 0110
    // 因为是负数,所以真正的数据是-1 取反
    //即  1 010 0101 取反:1 101 1010 得-90
    char a = 79;
    char b = -23;
    char c = a ^b;
    printf("%d\n", c);//-90

    return 0;
}

<<和>> :移位运算符

  • a<<2: 位左移
  • 2>>a: 位右移
    技巧⚠️:
    a<<n,相当于乘以2的n次幂;
    a>>n,a如果是非负数,相当于除以(/取整)2的n次幂
1000 0101 位左移两位
image.png
int main(int argc, char *argv[]) {

    //分析:a的存储形式就是他本身:0010 1101
    //坐移动两位:变成:1011 0100
    //因为1 所以是负数:-1取反:所以是1100 1100 即-76
    char a = 45;
    char b = a << 2;
    printf("%d\n", b);//-76
    return 0;
}
1000 0101 位右移两位

如果正数:位右移2位,最高位补俩0
如意负数:位右移2位,有的系统补俩0,有的系统补俩1(windows是补11,macbook pro测试也是补11)

//正数的时候:
int main(int argc, char *argv[]) {

    //分析:a的存储形式就是他本身:0010 1101
    //坐移动两位:变成:0000 1011 即11
    char a = 45;
    char b = a >>2;
    printf("%d\n", b);//11

    return 0;
}
//负数的时候,我的电脑是最高位补1
#include "c3.h"
int main(int argc, char *argv[]) {

    //分析:a的存储形式就是他的取反+1:
    // -45:1010 1101,取反+1:1101 0011
    //坐移动两位:变成:1111 0100
    //因为是负数,1111 0100 是他的存储数据,他真正的数据是:
    // -1 再取反:-1: 1111 0011 取反:1000 1100 即-12
    char a = -45;
    char b = a >>2;
    printf("%d\n", b);//-12

    return 0;
}

技巧⚠️:

a<<n,相当于乘以2的n次幂;
a>>n,a如果是非负数,相当于除以(/取整)2的n次幂
位运算速度远远大于普通运算

#include "c3.h"

int main(int argc, char *argv[]) {

    char a = 6;
    char b = a << 3;//a左移动2位,相当于,6*2^3=48
    printf("%d\n", b);//48 :

    char c = 48;
    char d = c >> 3;//非负数a右移动3位,相当于,48/(2^3)
    printf("%d\n", d);//6
    return 0;
}

&=、|=、^=、>>=、<<=

跟+= 、-=一样。
a^=b :a=a^b;
...

2.位字段

这个方法移植性不是很好,位运算完全可以实现字段的所有功能,所以位字段了解为主。


image.png

相关文章

  • 3、小众运算符の大课堂(一)

    较为简单の位运算符: & 位与运算| 位或运算^ 位异或运算~ 位取反运算 举例: 要做位运算,首先要把数据转...

  • 位运算及其应用

    内容概要: 位运算基本操作 基于位运算的状态压缩 位运算经典应用 位运算解N皇后问题 位运算 符号描述规则&与1&...

  • 位运算及用位运算实现权限控制

    请自行补习位运算相关知识 位运算 位运算示例 权限控制

  • 开发基础随笔之位运算符(Bitwise Operators)

    位运算符,属于算术运算符 按位逻辑运算符: 位移运算符: 位运算符的运算数只能是整数 位移运算符:按位左移 a<<...

  • 强大的位运算符

    位取反运算符 位取反运算符(~)是对所有位的数字进行取反操作位取反运算符.png 位与运算符 位与运算符(&)可以...

  • 位运算

    位运算 1. &:按位与 规律:一假则假任何位上的数和1相&得到的结果还是那个数 2. |:按位或 规律:一真则真...

  • 位运算

    https://leetcode.com/problems/gray-code/description/这个位运算...

  • 位运算

    位运算符比一般的算术运算符速度要快,而且可以实现一些算术运算符不能实现的功能。如果要开发高效率程序,位运算符是必不...

  • 位运算

    1.不用加减乘除做加法 解法:分为三步①各位相加不进位,即先按位异或;②做进位,按位与并左移位;③结果相加,直至没...

  • 位运算

    位运算不仅可以简化某些复杂的操作,而且具有更快的计算速度。典型的应用就是除法,交换两个数值,以及在一个数组中寻找只...

网友评论

      本文标题:位运算

      本文链接:https://www.haomeiwen.com/subject/ibxaphtx.html