题目链接:IP Networks - UVA 1590 - Virtual Judge (vjudge.net)
题目非常简单,但是还是想学一些不了解的东西,然后我就去百度了大佬的代码,发现了一些我不了解的知识,
大佬代码链接:http://t.csdn.cn/Nyeu2
关于位运算符的用法与介绍:
位运算符就是由int型转换为二进制型的一种快捷方式,而常见的位运算符有<<,>>,~,^,&,|,这些位运算符可以对二进制进行运算,
1,左移运算符(<<),右移运算符(>>)
用一个例子来说吧,比如有一个int型整数a为2(其二进制为10),假设一个int占32位,
int b=a<<3;//b的二进制形式为10000,int类型要占满,但是其他高位都是零;
int c=a>>1;//b的二进制形式为1,零占位同上;
int d=a<<31;//d的二进制形式为0,10左移31为原本10中的1恰好没有了;
2,位求反运算符(~)
将运算对象逐位求反后生成一个新值,就是将二进制的1变成0,0变成1,
int a=-1;//(二进制原码为11111111 11111111 11111111 11111111)
int b=~a;//(b的十进制整数为0)
ps:有没有今天才知道二进制如何表示负数的呢?我想说一下为好,QAQ
在二进制码中,采用最高位是符号位的方法来区分正负数,正数的符号位为0、负数的符号位为1。剩下的就是这个数的绝对值部分。通过将负数转为二进制原码,再求其原码的反码,最后求得的补码即负数的二进制表示结果。
比如整数-1。先取1的原码:00000000 00000000 00000000 00000001,得反码: 11111111 11111111 11111111 11111110,最后得补码: 11111111 11111111 11111111 11111111,即-1在计算机里用二进制表示结果。
ps.ps:
在计算机中,除了十进制是有符号的外,其它如二进制、八进制、16进制都是无符号的。补码中正数与原码正数表示一样。补码中负数是采用2的补数来表示的,即把负数先加上2.以便将正数与负数的相加转化为正数与正数相加,从而克服原码表示法做加减法的困难。
由于负数的补码是2一|x|,故求负数的补码时,实际上要做一次减法,这是不希望的。可以发现,只要将原码正数的每位取反码,再在所得数的末位加1,则正好得到负数的补码,这简称为对尾数的“取反加1”。
二进制的补码:对求一个数的补码有一个简单的口诀,若X是正数,则X的补码等于原码,若X是负数,X的补码就是在求出原码的基础上数值位全部取反后在最后一位加1。
3,剩余位运算符(^,&,|)
这三个运算符就相对简单了,他们的运算符合逻辑加或者特定的规则
int a=2,b=3;
int c=a^b;//c的二进制为1,运算规则为“1+1=0,0+0=0,1+0=1”
int d=a&b;//运算规则通逻辑并;
int e=a|b;//运算规则同逻辑或;
关与使用bitset类型可以将整数直接转化为二进制
bitset的作用就是使得位运算变得简便,bitset类定义在头文件bitset中,设一个int类型有32位,则可以定义bitset<32> p;
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
string s;
//bitset<32> p(a);
bitset <32> b(5);
s=b.to_string();
cout<<s<<endl;
cout<<b<<endl;
return 0;
}
上面字符串s和b打印在控制台上是一样的,但是一个是字符‘0’和‘1’,一个是int0和1,可以更方便进行操作。