前言
一些非常基础的东西, 在实际工作中没有用到, 很少用到. 一旦遇到, 又不知所云. 最近遇到一个问题, 把一个 int16(short) , 两个 bool 变量整合成一个 int32(int), 当听到这个要求时, 我第一反应是不是需求弄错了, 后来才发现是自己才疏学浅, 这里就需要位运算相关的概念.
这里补充一下这几个基本概念
位, 字节, 字符(英文字母), 汉字, KB,MB,GB,TB 的关系
1. 位: bit, 也叫比特位, 是计算机表示数据最小的单位, 用二进制 0 和 1 来存储
2. 字节: byte,1byte(1B)=8b, 一个字节 = 8 位
3. 字符: char,1char=2byte=16b,1 个字符 = 2 个字节 = 16 位
- KB,1KB=1024byte(1024B)
- MB,1MB=1014KB
- GB,1GB=1024MB
- TB,1TB=1024GB
一个汉字占两个字节, 也就是 32 位, 一篇 1000 字的文章, 大概就是 321000 的二进制 0 或 1 .
一个 10M 的短视频, 也就是 10M=1024KB10=1024 字节 1010=1024b1010*8
大概就是 919200 个二进制的 0 和 1 了
short 是 16 位, int 是 32 位, long 是 64 位
1. 什么是位运算
在掌握位运算之前, 应该清楚什么是位运算? 什么样的数据类型可以进行位运算? 云运算的结果是什么?
1. 位运算的对象是 int ,char 类型, 简而言之就是对二进制的 1101(13)进行运算
2. 位运算的结果是整型
符号 | 意义 | 运算对象类型 | 运算结果类型 | 示例 |
---|---|---|---|---|
~ | 逻辑非运算 | 整型、char | 整型 | ~a |
& | 逻辑与运算 | a&b | ||
| | 逻辑或运算 | a|b | ||
<< | 位左移运算 | a<<2 | ||
>> | 位右移运算 | a>>2 |
2. 位逻辑与运算
& 与运算是将两个运算对象按位于进行与运算.
规则是:
- 1&1=1
- 0&1=0
- 0&0=0
如图:
15 的二进制是 0000 1111
20 的二进制是 0001 0100
15&20 的结果就是 0000 0100 即结果是 4
3. 位逻辑或运算
| 位逻辑或运算是将两个运算对象按位进行或运算, 运算的规则是
- 1|1=1
- 1|0=1
- 0|0=0
如 15|20 的结果计算结果就是 31 即二进制 0001 1111
0000 1111(15 的二进制) | 0001 0100(20 的二进制)= 0001 1111 结果是 31
4. 位逻辑异或运算
^ 位逻辑异或运算 是将两个运算对象按位进行异或运算, 规则是:
1 异或 1 等于 0
1 异或 0 等于 1
0 异或 0 等于 0
即: 相同得 0, 相异得 1.
0000 1111 ^ 0001 0100= 0001 1011 结果是 27
5. 位逻辑左移运算
位逻辑左移运算是将按位向左边移动若干位, 左移后空出的部分为 0
比如 15 的二进制 0000 1111 左移 8 位就是 1111 0000 0000(15<<8)结果是 3840
左移 3 位 (15<<3) 就是 0111 1000 结果是 120
左移就是相当于乘, 左移 1 位就是相当于乘以 2 的 1 次方, 左移 3 位就是相当于乘以 2 的 3 次方, 左移 8 位就是相当于乘以 2 的 8 次方
a<<1 =a 乘以 2 的 1 次方
a<<2 =a 乘以 2 的 2 次方
a<<3 =a 乘以 2 的 3 次方
6. 位逻辑右移运算
位逻辑右移运算是将按位向右边移动若干位, 右移后空出的部分为 0
比如 0000 1111(15)左移 3 位 (15<<3) 就是 0000 0001(1)
右移相当于整除, 右移 1 位相当于除以 2 的 1 次方, 右移 2 相当于除以 2 的 2 次方.
a>>1 = a 整除 2 的 1 次方
a>>2 = a 整除 2 的 2 次方
a>>3 = a 整除 2 的 3 次方
7. 位运算的作用
如将一个月的签到记录保存到 1 个 int 类型中, 权限设置, 将 4 个 short 合并成一个 long 类型, 16 个 bool 类型合并成 1 个 short.
如这个问题所示
需求: C# 用两个 short, 一个 int32 拼成一个 long 型
要求: 现在有两个 short 和一个 int, 需要拼成一个 long 型, 高 16 位用 short, 中间 32 位用 int, 最低 16 位用另外一个 short
https://bbs.csdn.net/topics/392202825?page=1
做法就是:
((long)shortA << 48 )+ ((long)intA << 16)+ shortB=longResult
讲解:
高 16 位的 shortA 先左移 48, 那么 longResult 64 位的最左边 16 位 (高 16 位) 就是 shortA
中间 32 位 intA 就是先将 intA 左移 16 位, 那么这个 longResult 的中间 32 位就是 intA
低 16 位就是最后剩下的 16 位用 shortB.
那么疑问来了可以通过 longResult 返推出 shortA,shortB,intA. 当然是不能这是直接相加.
能反推出的只能是
((long)shortA << 48 ) 16 位二进制 0 或 1 的字符串
((long)intA << 16) 32 位二进制 0 或 1 的字符串
shortB 16 位二进制 0 或 1 的字符串
将这三个字符串拼接成 64 位二进制字符串, 再将这个 64 位二进制字符串转成一个 long.
来源: https://www.cnblogs.com/zhangmumu/p/10781201.html