计算机中数值全部用补码表示
正数: 源码,反码,补码均相同
负数: 补码 = 反码 + 1
-1 源码: 1000 0000 0000 0000 0000 0000 0000 0001
-1 反码: 1111 1111 1111 1111 1111 1111 1111 1110
-1补码: 反码+1 = 1111 1111 1111 1111 1111 1111 1111 1111
-1用二进制补码表示为32个1
为什么呢?
由于int 在32位和64位机器中均占用4个字节(1字节=8bit) ,所以-1的二进制补码为32个1
<1> 进制的转换
(1)十进制转二进制:
6->110 ;
(2)二进制转十进制
110 = 1*2^2 + 1*2^1 + 0*1^0 = 6 ;
(3)十进制小数转二进制
6.8125 转二进制
整数部分如上述(1)所示 6 -> 110 ,
小数部分:
0.8125 * 2 = 1.625 取整数 1 余小数部分0.625
0.625 * 2 = 1.25 取整数 1 余小数部分0.25
0.25 * 2 = 0.5 取整数 0 余小数0.5
0.5 * 2 = 1.0 取整数1 余小数0.0
结束
小数部分为1101
因此
6.8125 转二进制为 110.1101
(4) 二进制小数转十进制
110.1101转十进制 :
110.1101 = 1*2^2 + 1*2^1 + 0*1^0 . 1*2^-1 + 1*2^-2 + 0*2^-3 + 1*2^-4
其它进制转换不再陈述
<2> 位运算
按位与 a & b
按位或 a | b
按位异或 a ^ b
按位取反 ~a
左移 a << b
右移 a >> b
(3) 位运算基本规律:
1101 & 1011 = 1001
1101 | 1011 = 1111
~1101 = 0010
①移位操作
左移时,正负都一样右边加0
正数: 0000 1101 << 1 = 0001 1010
负数: 1000 1101 << 1 = 0001 1010
右移时,正数左边加0,负数左边加1
正数: 0000 1101 >> 1 = 0000 0110
负数: 1000 1101 >> 1 = 1100 0110
右移相当于除2
左移相当于乘2
②异或
1101 ^ 1011 = 0110
应用不用第三个参数交换a b
a = a^b;
b = a^b;
a = a^b;
③与
去掉一个数字的二进制的最后一个1
n = n&(n-1) ;
获取一个数字的二进制的最后一个1
n = n&~(n-1) ;
或
n = n&(-n) ;
检测第i位是否为1
bit = n & ( 1 << i );
清除第i位(即置为0)
n = n & ~( 1 << i );
第i位置为1
n = n | ( 1 << i );
第i位置取反
n = n ^ ( 1 << i );
位运算实例:
<pre name="code" class="cpp">#include <iostream>
using namespace std;
/*
题目:任意给定一个32位无符号整数n,求n的二进制表示中1的个数,
比如n = 5(0101)时,返回2,n = 15(1111)时,返回4
*/
//右移法:当输入负数时,出现死循环
int NumberOf1(int n)
{
int count = 0;
while (n)
{
if (n & 1)
{
count++;
}
n=n >> 1; //右移相当于除以2
}
return count;
}
//左移法: 循环次数等于整数二进制的位数,即32位的整数需要循环32次
int NumberOf1t(int n)
{
int count = 0;
unsigned int flag = 1;
while (flag)
{
if (n&flag)
{
count++;
}
//flag = flag * 2;等价于flag = flag << 1;但位运算速度更快
flag = flag << 1;
}
return count;
}
//把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变为0.
//那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作.
int NumberOf1tt(int n)
{
int count = 0;
while (n)
{
count++;
n = (n - 1)&n;
//cout << n << endl;
}
return count;
}
//n左移法:打印整数的二进制数
void IntToBit(int n)
{
int flag = 1;
while (flag)
{
if (n & flag)
{
cout << 1;
}
else
{
cout << 0;
}
flag = flag << 1;
}
cout << endl;
}
//递归实现,从第一位开始输出,即递归之前输出
void IntToBit2(int n, int flag)
{
if (flag == 0)
{
return ;
}
if (n & flag)
{
cout << 1;
}
else
{
cout << 0;
}
IntToBit2(n, flag<<1);
}
//递归实现,从最后一位开始输出,即先递归到二进制的最高位,再输出
void IntToBit3(int n, int flag)
{
if (flag == 0)
{
return ;
}
IntToBit3(n, flag<<1);
if (n & flag)
{
cout << 1;
}
else
{
cout << 0;
}
}
/*题目47: 不用加减乘除做加法*/
int Add(int num1, int num2)
{
//sum记录相加的值,carry记录进位
int sum, carry;
do
{
//各位相加不进位
sum = num1 ^ num2;
//做进位
carry = (num1&num2) << 1;
num1 = sum;
num2 = carry;
} while (num2 != 0);
return num1;
}
//求数值的相反数,即反码+1
int Opposite(int num)
{
//反码+1
return Add(~num, 1);
}
//二进制减法
int Subtract(int num1, int num2)
{
return Add(num1, Opposite(num2));
}
//二进制乘法
int Multiply(int num1, int num2)
{
//判断两个数相乘之后的正负号(异或:一正一负返回true,两正或两副返回false)
bool isNeg = (num1 > 0) ^ (num2 > 0);
//判断两个数的正负,并统一转化为正数
int x = num1 > 0 ? num1 : Opposite(num1);
int y = num2 > 0 ? num2 : Opposite(num2);
int ans = 0;
while (y != 0)
{
if (y & 1)
{
ans = Add(ans, x);
}
y=y >> 1;
x=x << 1;
}
return isNeg ? Opposite(ans) : ans;
}
//查找最小值
int Min(int a, int b)
{
return a < b ? a : b;
}
//将被除数的j位之前的所有位都置为0(由于我们这里都已经转换为正数,所以不用考虑符号位)
int DeleteHigeBite(int num,int j)
{
for (int i = j; i <= 31; i++)
{
num = num&~(1 << i);
}
return num;
}
//二进制除法
int Divide(int num1, int num2)
{
//判断两个数相乘之后的正负号(异或:一正一负返回true,两正或两副返回false)
bool isNeg = (num1 > 0) ^ (num2 > 0);
//判断两个数的正负,并统一转化为正数
int x = (num1 > 0) ? num1 : Opposite(num1);
int y = (num2 > 0) ? num2 : Opposite(num2);
int ans = 0;
for (int i = 31; i >= 0; i--)
{
//让x右移i位找到被除数x可以被除数除尽的点
//即模拟除法运算:被除数x从左侧开始被除
if ((x >> i) >= y)
{
//去掉i位之前的所有位都(即置为0),让x从剩下的被除数开始
//(由于我们这里都已经转换为正数,所以不用考虑符号位)
x = DeleteHigeBite(x, i);
ans = Add(ans, 1 << i); //商
}
}
return isNeg ? Opposite(ans) : ans;
}
int main(void)
{
cout << NumberOf1(7) << endl;
/*
计算机中数值均用补码表示
正数的原码反码补码全相同
负数的反码=原码取反,补码=反码+1.
*/
cout << NumberOf1t(-1) << endl; //32
cout << NumberOf1tt(-7) << endl; //32
//打印整数5的二进制,
//由于左移相当于乘2,右移相当于除2,则说明二进制右侧为最低位
IntToBit(5);
IntToBit2(5,1);
cout << endl;
IntToBit3(5, 1);
cout << endl;
/*题目47: 不用加减乘除做加法*/
cout << Add(5, 17)<<endl; // + 22
cout << Subtract(5,17) << endl; //- -12
cout << Multiply(-5, -10) << endl; //85
cout << Divide(-14,3) << endl; //取整除法 -4
return 0;
}