0进制转换和位运算
计算机中存储单位
什么是bit
bit是计算机中最小的信号但愿,可以表示高电平或者低电平。
以二进制“001”为例, 每一位都是一个bit。二进制只能由0/1组成,所以正好可以表示bit。
什么是byte
1个bit只能表示两种信号或者两种状态,表示的范围很小,例如英文字母26个就无法表示。所以规定8个bit一组作为一个数据的最小单元。即8bit=1byte。ASCII码表中的一个字符为一个byte。
1位二级制数可以表示的状态的个数是2种。0 1
2位二进制数可以表示的状态的个数是2的2次幂。00 01 10 11
3位二进制数可以表示的状态的个数是2的3次幂。
8位二进制数可以表示的状态的个数是2的8次幂。也就是256种。
1kb=1024byte
1mb=1024kb
1gb=1024mb
1tb=1024gb
写法和程序输出方式
不同进制的写法(c语言和java语言)
二进制由0,1组成。以0b开头
//合法的二进制
int a = 0b101; //换算成十进制为 5
int b = -0b110010; //换算成十进制为 -50
int c = 0B100001; //换算成十进制为 33
//非法的二进制
int m = 101010; //无前缀 0B,相当于十进制
int n = 0B410; //4不是有效的二进制数字
八进制由0-1组成,以0开头
//合法的八进制数
int a = 015; //换算成十进制为 13
int b = -0101; //换算成十进制为 -65
int c = 0177777; //换算成十进制为 65535
//非法的八进制
int m = 256; //无前缀 0,相当于十进制
int n = 03A2; //A不是有效的八进制数字
十六由0-9、a-f组成进制以0x开头
//合法的十六进制
int a = 0X2A; //换算成十进制为 42
int b = -0XA0; //换算成十进制为 -160
int c = 0xffff; //换算成十进制为 65535
//非法的十六进制
int m = 5A; //没有前缀 0X,是一个无效数字
int n = 0X3H; //H不是有效的十六进制数字
二进制数、八进制数和十六进制数的输出
short
int
long
八进制
%ho
%o
%lo
十进制
%hd
%d
%ld
十六进制
%hx 或者 %hX
%x 或者 %X
%lx 或者 %lX
#include
int main()
{
short a = 0b1010110; //二进制数字
int b = 02713; //八进制数字
long c = 0X1DAB83; //十六进制数字
printf("a=%#ho, b=%#o, c=%#lo\n", a, b, c); //以八进制形似输出
printf("a=%hd, b=%d, c=%ld\n", a, b, c); //以十进制形式输出
printf("a=%#hx, b=%#x, c=%#lx\n", a, b, c); //以十六进制形式输出(字母小写)
printf("a=%#hX, b=%#X, c=%#lX\n", a, b, c); //以十六进制形式输出(字母大写)
return 0;
}
在占位符中的#代表输出前缀,运行结果:
a=0126, b=02713, c=07325603
a=86, b=1483, c=1944451
a=0x56, b=0x5cb, c=0x1dab83
a=0X56, b=0X5CB, c=0X1DAB83
在内存中的表示方式
数值类型数据通常采用二进制数的最高位来表示符号,用0表示正数,1表示负数。
例如二进制数+1101000在计算机内表示为
内存中
1
1
1
0
1
0
0
0
真值
+
1
1
0
1
0
0
0
所有的数在计算机中都是以补码的形式存储的。正数的补码 == 原码。
原码、反码、补码
原码
原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值
二进制位的首位标识该二进制数是一个正数还是负数,正数为0,负数为1
正数: 10 的原码 –> 0000 0000 0000 0000 0000 0000 0000 1010
负数:-10 的原码 –> 1000 0000 0000 0000 0000 0000 0000 1010
反码
正数的反码 == 原码
负数的反码是在其原码的基础上,符号位(首位)不变,其余各个位取反
正数: 10 的原码 –> 0000 0000 0000 0000 0000 0000 0000 1010
负数:-10 的原码 –> 1000 0000 0000 0000 0000 0000 0000 1010
正数: 10 的反码 –> 0000 0000 0000 0000 0000 0000 0000 1010
负数:-10 的反码 –> 1111 1111 1111 1111 1111 1111 1111 0101
补码
正数的补码 == 原码
负数的补码是在其反码的基础上加1
正数: 10 的原码 –> 0000 0000 0000 0000 0000 0000 0000 1010
负数:-10 的原码 –> 1000 0000 0000 0000 0000 0000 0000 1010
正数: 10 的反码 –> 0000 0000 0000 0000 0000 0000 0000 1010
负数:-10 的反码 –> 1111 1111 1111 1111 1111 1111 1111 0101
正数: 10 的补码 –> 0000 0000 0000 0000 0000 0000 0000 1010
负数:-10 的补码 –> 1111 1111 1111 1111 1111 1111 1111 0110
不同进制数据计算和转换
不同进制数据计算
十进制数据计算 略
二进制数据计算 每位相加,逢2进1.
0b1101+0b1101010=0b1110111
1 1 0 1
1 1 0 1 0 1 0
1 1 1 0 1 1 1
八进制数据计算:每位相加,逢8进1
0127+0765=1114
1 2 7
7 6 5
1 1 1 4
十六进制数据计算:逢16进1。其中a=10;b=11;c=12;d=13;e=14;f=15;
0x1ab+0x99a=b45
1 a(10) b(11)
9 9 a(10)
b(11) 20-16=4 21-16=5
任意进制转十进制
系数:每一位的数字
以157为例,个位系数是7,十位系数是5,百位系数是1
基数:几进制,基数就是几。十进制基数为十。
权:一个数据从右往左数,从0开始对每一位数据进行编号,这个编号就是这个位置上的权。
数字:157
权 :210
转换方式:任意进制到十进制的转换都等于“这个数据的各个位上的系数乘以基数的权次幂相加的和”
十进制:157=7X10^0+5X10^1+1X10^2
二进制:0b110=0x2^0+1×2^1+1×2^2=0+2+4=6
八进制:0110=0x8^0+1×8^1+1×8^2 = 0+8+64=72
十六进制:0xabc=12×16^0+11×16^1+10×16^2=12+176+2560=2748
十进制转任意进制
转换方式:把十进制的数字除以基数取余数,直到商为0,再将余数反转。
100转二进制为 0b1100100
100/2=50余0
50/2=25余0
25/2=12余1
12/2= 6余0
6/2= 3余0
3/2= 1余1
1/2= 0余1
100转8进制为0144
100/8=12余4
12/8= 1余4
1/8= 0余1
100转16进制为0x64
100/16=6余4
6/16=0余6
十进制和二进制利用8421码快速转换
二进制
1
1
1
1
1
1
1
1
十进制
128
64
32
16
8
4
2
1
11011=1+2+0+8+16=27
位运算
&
|
^
~
<<
>>
>>>
按位与
按位或
按位异或
按位取反
左移
右移
无符号右移
位运算符连接二进制数值,返回二进制数值。
补码:原码取反+1
&按位与[双目运算符—连接两个操作数]
同1为1,否则为0
3&4的结果:
int 3的二进制:0b11。由于每个int占4个字节也就是8的4次方个bit,即32位。
int 4的二进制:0b100
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0000
即3&4=0
|按位或[双目运算符—连接两个操作数]
只要有一个为1则结果为1,否则为0
3|4的结果
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0111
即3|4=111=7
^按位异或[双目运算符—连接两个操作数]
相同为0,不同为1
3^4的结果
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 0111
即3^4=111=7
一个数据对相同的数据异或两次,其值不变。
~按位取反[单目运算符—一个操作数]
每位取反
~3
0000 0000 0000 0000 0000 0000 0000 0011
1111 1111 1111 1111 1111 1111 1111 1100
首位为1说明是负数,负数以其正值的补码形式存在。
所以想转为10进制的话就是已知补码求原码,即补码减1,然后取反,但是减法太麻烦。
还有一种思路就是将负数的补码先取反,然后加1,最高位置换为1就是原码。
1111 1111 1111 1111 1111 1111 1111 1100 取反
0000 0000 0000 0000 0000 0000 0000 0011 加1
0000 0000 0000 0000 0000 0000 0000 0100 最高位置换为1
1000 0000 0000 0000 0000 0000 0000 0100 即为-4
>>左移 <
让操作数乘以2的n次幂 n就是移动的位数
让操作数除以2的n次幂 n就是移动的位数
int i=3<<2;//3*2^2=12
往左边移动两位,右边空出两位,左边两位被挤掉,右边空位用0补全。
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 1100 0X2^0+0*2^1+1X2^2+1X2^3=4+8=12
int i=32>>2;//32/2^2=8
往右边移动两位,左边空出两位,右边两位被挤掉,左边空位用看符号位,符号位为0用0补,符号位为1用1补。
0000 0000 0000 0000 0000 0000 0010 0000
0000 0000 0000 0000 0000 0000 0000 1000 0x2^0+0x2^1+0x2^2+1×2^3=8
int i=-32>>2=-8
原码1000 0000 0000 0000 0000 0000 0010 0000
反码1111 1111 1111 1111 1111 1111 1101 1111
补码1111 1111 1111 1111 1111 1111 1110 0000
负数右移两位是对补码右移两位得到右移后的补码
补码1111 1111 1111 1111 1111 1111 1111 1000
补码取反,加1,高位置换为1即为原码。
取反0000 0000 0000 0000 0000 0000 0000 0111
加一0000 0000 0000 0000 0000 0000 0000 1000
原码1000 0000 0000 0000 0000 0000 0000 1000 即为-8
本文详细介绍了C语言中不同进制的表示方法,包括二进制、八进制和十六进制,并提供了合法和非法的写法示例。同时,讲解了如何在C语言中进行二进制、八进制和十六进制的输出。此外,文章还讨论了计算机中数值的存储方式,包括原码、反码和补码的概念,以及位运算如按位与、按位或、按位异或等的操作。

被折叠的 条评论
为什么被折叠?



