二进制与位运算
前题知识
1、每一个变量被指定为一个确定类型,在编译时就能为其分配相应的储存单元。如指定a,b为int型。TurboC为a和b分配两个字节的变量。变量名实际上是一个名字对应,代表一个地址。在对程序编译连接时,由编译系统给每一个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。
2、为变量分配字节的数量,每种编译器是不相同的。即编译器指定每种变量分配的字节数。
3、一个字节是是8位。一位只能表示0或1。按排列关系计算,每一字节表达不同信息的最大数量是2的8次幂。
4、sizeof(...)函数。计算变量对应的字节数。
5、二进制与十进制的相互转化
十进制转换为二进制数应该将整数部分和小分部分分别进行转换(这里我们只研究整数)
十进制转化为二进制方法:除2取余法
求余规则:(1)a/2=2*b+c,c=0 or 1。余取为c
(2)示余规则:1)a<b时,a%b,余数为a (自己描述的求余规则)
2)a=b时,a%b余数为0
3)a>b时,a%b,max(nb)=<a,余数为a-nb
除2规则:1、商为0时中止。a<b,a/b,则商为0(自己描述的规则)
2、余数倒排,产生二进制数
例:0D=0B,1D=1B,2D=10B,3D=11B,.......10B=1010B.......
215D
2 | 215 .......................................1
2|107 .......................................1
2|53 .......................................1
2|26 .......................................0
2|13 .......................................1
2|6 .......................................0
2|3 .......................................1
2|1 .......................................1
0 ...........商为0,终止运算
215D=11010111B
二进制转化成十进制
二进制转化成十进制方法:位权展开求和
例:11001B=1×24+1×23×+0×22+0×21+1×20
=16+8+1
=25D
6、设int为2字节,int i=297;i=100101001。它在计算机内存中的表示如下
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
7、二进制数的运算规则
1)加法运算规则
0+0=0, 0+1=1,1+0=1,1+1=0(进拉)
例:
|
0 |
1 |
1 |
0 |
1 |
1 |
+ |
0 |
1 |
0 |
0 |
0 |
1 |
结果 |
1 |
0 |
1 |
1 |
0 |
0 |
2)减法运算规则
0-0=0, 0-1=1(向上借位), 1-0=1, 1-1=0
|
1 |
0 |
0 |
0 |
1 |
1 |
- |
0 |
1 |
1 |
0 |
0 |
1 |
结果 |
0 |
0 |
1 |
0 |
1 |
0 |
3)乘法运算规则
0×0=0, 0×1=0, 1×0=0, 1×1=1
例:
|
|
|
1 |
0 |
1 |
1 |
|
|
× |
1 |
0 |
0 |
1 |
|
|
|
1 |
0 |
1 |
1 |
|
|
0 |
0 |
0 |
0 |
|
|
0 |
0 |
0 |
0 |
|
|
1 |
0 |
1 |
1 |
|
|
|
1 |
1 |
0 |
0 |
0 |
1 |
1 |
验算:11×9=99
位运算知识
1、位运算符 位运算符表
运算符 |
含义 |
解释 |
运算符 |
含义 |
解释 |
& |
按位与 |
一假既假 |
~ |
取反 |
0则1,1则0 |
| |
按位或 |
一真既真 |
<< |
左移 |
<<n ,左移n位 |
^ |
按位异或 |
同则假异则真 |
>> |
右移 |
>>n右移n位 |
2、各运算符举例
(1)“&”
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
(3) |
& |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
(5) |
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
(1) |
例:
(2) “|”
|
0 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
(50) |
| |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
(31) |
|
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
(63) |
(3) “^”
|
0 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
(57) |
^ |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
(42) |
|
0 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
(19) |
(4) “~”(略)
(5) “<<”
例:int a=64D a=a<<2 ,则a=?(设int 为2Byte)
解:a=63 ->1000000D
内存表示
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
左移两位,右补0
内存表示
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
即a=100000000B
转化成十进制:a=256
(6) “>>”。类推“<<”,既可理解“>>”
左边移入的是0还是1。要取决于所用的计算系统
3、各位算的特殊用法:
(1)“&”:清零;取一个数中某些指定的位。
(2)“^”使特点位翻转;与0相^保留原值;交换两个值,不用临时变量。
(3)“<<”有时相当于乘法。
(4)“>>”有时相当于除法。
4、利用字节的位传递表达信息。
改变一个字节某些位,来写入信息;读取一个字节的某些位,来读出信息。
改变和读出方法:利用上述位操作符。
例:打印出int类型的数的二位制表示
原理说明:(1)利用“&”操作符。想要保留哪位,原数就与一个数0...1..0进行&运算,
1所处的位置就是原数想要保留的位置。
(2) 取出这位的数:“&”操作后,原数的形式为0...x....0,x不是0,就是1,所以
0...x...0只可能有两个十进制表示的值,0,或者对应的唯一的十进制数判断
是不是其十进制值是不是0,就可以判断出该为是0还是1。然后写出数组
中对应的位置。
(3)确定0...1..0对应的十进制数
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
|
二 进 制 ( B ) |
D |
|||||||||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
0 |
0 |
4 |
|
|
|
|
|
|
|
|
|
|
|
|
1 |
0 |
0 |
0 |
8 |
|
|
|
|
|
|
|
|
|
|
|
1 |
0 |
0 |
0 |
0 |
16 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
32 |
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
64 |
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
128 |
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
256 |
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
512 |
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
1024 |
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
2048 |
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
4096 |
|
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
8192 |
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16384 |
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32768 |
归纳得D=1,D=2*D,其实这也是很好理解的。
编译系统VC6.0
代码如下(完全自己编写)
#include <stdio.h>
void getIntToBinary(int iPar,int [],int iLen);
void main()
{
int iByte=0;
//vc6.0给int 分配了四个字节的储存空间
//显式初始化
int arrb[32]={0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
int ilen=32;
int ipar=3000;
getIntToBinary(ipar,arrb ,ilen);
//打印数组,倒序打印
for(int i=ilen-1;i>-1;i--)
{
printf("%i ",arrb[i]);
if(0==(i%8)&i>1) //i>1,为了消除最后面的逗号
{printf(" , ");}
}
printf("/n");
}
/*
*功能:读出给定的十进制的整数的二进制数,以0D,01的形式,储存在给定的数组里
参数说明:int iPar 给定的十进制的整数
int * arr 储存结果的数组指针
int iLen 储存结果的数组指针的长度
*/
void getIntToBinary(int iPar,int * arr,int iLen)
{
int i=0;
int itemp=0;//位值
int iPared=0;//与运算后的数值
int iYU=1;//位被运算数初值
//
for(i=0;i<iLen;i++)
{
iPared=iPar&iYU;
if(iPared)
{
itemp=1;
}
else
{
itemp=0; //逻辑上更清楚
}
arr[i]=itemp;//将位值添入数组对应的位置上
iYU=2*iYU;
}
}
结果:0 0 0 0 0 0 0 0 , 0 0 0 0 0 0 0 0 , 0 0 0 0 1 0 1 1 , 1 0 1 1 1 0 0 0