- 进制
- 位运算
进制介绍
一种计数的方式,数值的表示形式。
常见的进制有:二进制、十进制、八进制和十六进制。
二进制:
0和1,C语言中表示0b开头或者0B开头。
八进制:
0,1,2,3,4,5,6,7 C语言中以0开头的数字,例如045
十进制:
自然数
十六进制:
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F C语言中以0x或者0X开头的数字
进制之间的转换:
其他进制转换成十进制的三要素:
1. 数位:数码在一个数中所处的位置。 一个序列,从右往左数位依次是0,1,2,3 ...
2. 基数: 几进制基数就是几
3. 位权: 位权 = 数码值 * 基数 ^ 数位
各位权之和就就是这个数转换成10进制后的表示形式。
十进制转二进制:
除2取余,把余数的序列倒过来就是该数的二进制表示。
二进制转十进制:
所有位权相加
二进制转十六进制:
整数部分,四位二进制从左向右结合;小数部分从右向左结合;
十六进制:
一拆四;
二进制转八进制:
三合一;
八进制转二进制:
一拆三;
机器数:
一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机 用一个数的最高位存放符号, 正数为0, 负数为1.
真值:
将带符号位的机器数对应的真正数值称为机器数的真值。
因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于 131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
原码、反码、补码:
数据在计算机中的存储方法: 数据在计算机内部是以补码的形式储存的
数据分为有符号数和无符号数:
无符号数都为正数,由十进制直接转换到二进制直接存储(其实也是该十进制的补码)即可。有符号数用在计算机内部是以补码的形式储存的。( 正数的最高位是符号位0,负数的最高位是 符号位1。
对于正数:反码==补码==原码。 对于负数:反码==除符号位以外的各位取反。补码=反 码+1)
以二进制的补码存储
正数:原码、反码、补码都相同
负数:反码 = 源码取反,补码 = 反码+1, 或者 补码 = 源码取反 + 1,前提都是符号位不变
正数的首位地址为0,其原码是由十进制数转换到的二进制数字
负数的首位地址为1,其原码后面的位也为10进制数转换过去的二进制数字,都是用补码方式表示 有符号数的。
1)原码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值.
2)反码
反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
3)补码
补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
位运算
位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的 char,short,int与long类型。
1)& 按位与 口诀: 同1为1,有0为0
只有对应的两个二进位均为1时,结果位才为1,否则为0
2) | 按位或 口诀:有1则1
只要对应的二个二进位有一个为1时,结果位就为1,否则为0
3) ^ 按位异或 口诀:同0非1
当对应的二进位相异(不相同)时,结果为1,否则为0
4)~ 取反
各二进位进行取反(0变1,1变0)
以上都是在二进制进行运算
1)<< 左移
1、各二进位全部左移n位,高位丢弃,低位补0
1)左移可能会改变一个数的正负性
2)左移1位相当于*2^n
举例:快速计算一个数乘以2的n次方
(8<<3 等同于8*2^3)
2)>> 右移
各二进位全部右移n位,保持符号位不变
x >> n,x的所有二进制位向右移动n位,移出的位删掉,移进的位补符号位
1、右移不会改变一个数的符号
2 右移 n 位就相当于/2^n
用途:快速计算一个数除以2的n次方 (8>>3 等同于8/2^3)
技巧:
1)任何数和1进行&操作,得到这个数的最低位
2)想把某一位置0,就让它某一位置与0进行&运算
练习题:
1 /* 2 编写一个移位函数,使移位函数既能循环左移又能循环右移。参数n大于0时便是左移,参数n小于0时便是右移 3 4 解释:循环右移:把右边移出的位放到左边移入的位 5 如: 1101 0101 1100 循环左移四位 0101 1100 1101 6 7 循环左移:把左边移出的位放到右边移入的位 8 */ 9 #include <stdio.h> 10 11 unsigned bitTransfer(unsigned, int);//函数声明 12 13 int main(int argc, const char * argv[]){ 14 unsigned a = 9; 15 int n = 10; 16 17 unsigned b = bitTransfer(a, n); 18 19 printf("无符号数9位移10位后的数是:%u\n", b); 20 21 } 22 /** 23 * @author 司英成, 15-06-25 21:06:59 24 * 25 * @param number 要移位的数 26 * @param n 移位的位数 27 * 28 * @return 移位后的数 29 */ 30 unsigned bitTransfer(unsigned number, int n){ 31 if (n > 0) 32 return (number << n) ^ (number >> (32 - n)); 33 else{ 34 n = - n; 35 return (number >> n) ^ (number << (32 - n)); 36 } 37 }