每天进步一点点~加油~
8.1 位运算:
程序中的所有数都是以二进制的形式存在的,位运算就是直接对整数在内存中的二进制数进行位的操作运算,二进制从右往左,0为开始位。
含义 | 运算符 | 实例 |
---|---|---|
与运算(同时为1取1) | & | 1010 & 1001=1000 |
或运算(有一位为1取1) | | | 1010 & 1001=1011 |
左移(右边补位整体左移) | << | 1010 <<=0001 0100 |
右移(右边去位整体右移) | >> | 1010 >>=0101 |
取反(按位取反) | ~ | ~1010=0101 |
异或(相同取1,不同取0) | ^ | 1010 ^ 1001=1100 |
主要看看十六进制是如何右移左移运算的,来几个例子:
8.2 右移: 去掉了右侧两位,值减小
tianjain@tianjain-TM1701:~$ echo "ibase=16;obase=2;3A"|bc
111010 #看看3A的二进制
tianjain@tianjain-TM1701: ~$ a=$((0x3A>>2)) #将十六进制右移两位
tianjain@tianjain-TM1701:~$ echo $a
14 #右移后的十进制数
tianjain@tianjain-TM1701:~$ echo "ibase=10;obase=2;14"|bc
1110 #右移后的二进制数
8.3 左移:右测补了两位,整体值增加
tianjain@tianjain-TM1701:~$ echo "ibase=16;obase=2;3A"|bc
111010
tianjain@tianjain-TM1701:~$ a=$((0x3A<<2))
tianjain@tianjain-TM1701:~$ echo $a
232
tianjain@tianjain-TM1701:~$ echo "ibase=10;obase=2;232"|bc
11101000
8.4 与运算,取值:
假设我需要3A的第3位到第5位十进制值是多少,这就需要我们用与运算来取值了,[5:3],左闭右闭
tianjain@tianjain-TM1701:~$ echo "ibase=16;obase=2;3A"|bc
111010
tianjain@tianjain-TM1701:~$ a=$((0x3A>>3 &7))
tianjain@tianjain-TM1701:~$ echo $a
7
tianjain@tianjain-TM1701:~$ echo "ibase=10;obase=2;7"|bc
111
tianjain@tianjain-TM1701:~$
取值的时候就需要我们右移相应的位数,再与1相与,则可以取出本身的值。
echo “ibase=16;obase=2;3A”|bc
是用来转换进制的通用公式,ibase代表当前进制,obase代表你将要转的进制,3A是你当前的值,通过bc的方法。
a=$((0x3A>>3 &7))
对十六进制进行操作后,最终转换为是十进制。当然也可以直接使用十进制进行位运算,那会更加简单
8.5 进制转换:
- 任意进制转十进制方法:
$((BASE#NUMBER))
$((2#1101010))
- 进制任意转换公式:
echo "ibase=16;obase=2;3A"|bc
3. 注意点,我们通常转换的进制都是为无符号型的进制数,也就是说你所转的数字都为正数,那么当数字为负数时我们应该如何处理呢!
我们通常用二进制补码的形式来表示负数,最高位置1代表为负数。
原码:
原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值
二进制位的首位标识该二进制数是一个正数还是负数,正数为0,负数为1
正数的原码 == 正数绝对值的二进制数
负数的原码 == 负数绝对值的二进制数并且首位标识置1
反码:
正数的反码 == 原码
负数的反码 == 是在其原码的基础上,符号位(首位)不变,其余各个位取反
补码:
正数的补码 == 原码
负数的补码 == 原码除符号以外各位取反,然后最后一位加1
类型 | 5 | -5 |
---|---|---|
原 码 | 0101 | 1101 |
反码 | 0101 | 1010 |
补码 | 0101 | 1011 |
问题:如何将有符号的十六进制转换为有符号的十进制数
width=8 二进制位宽
hex="十六进制数"
des=$((hex))
if [ des -gt 2^($width-1) ];then #判断最高位是否存在
number=$(($des-2^width)) #如果为有符号的,将补码减去整体值得到真实值
else
number=des