下面的例子对位运算:&与、|或、^异或、~非的进行了基础使用的演示及一些具体问题的实现。
概念简述:
& 按位与,两个二进位均为1时, 结果位为1, 否则为0。*用来遮罩,取出为1的值*。
| 按位或,两个二进位只要有一个为1则为1,否则为0。*用来置1*。
//^ 异或运算,不同为1,相同为0,*用来取反*
~ 按位取反,如:101 取反为010。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//位运算演示
namespace Bit
{
class Program
{
//输出二进制方法
static void WriteBit(string s, uint n)
{
Console.WriteLine(s + ": " + Convert.ToString(n, 2));
}
// 0. 基本位运算操作符举例
static void Test()
{
uint n;//uint:无符号的32位整数,取值范围:0到4,294,967,295。Int带符号32位整数范围为:-2,147,483,648 到 2,147,483,647
//将1的二进制左移四位,相当于x=1*2的4次方=16,转换为二进制即10000。
n = 1 << 4;
//0000 0000 0000 0000 0000 0000 0000 0001
//0000 0000 0000 0000 0000 0000 0001 0000
WriteBit("1<<4", n);//输出10000
n = 0b11111111;
//直接输出二进制11111111,ob代表二进制
WriteBit("n", n);
n &= 0b10101010;//&运算后新值赋给n
// 11111111
//& 按位与,两个二进位均为1时, 结果位为1, 否则为0。*用来遮罩,取出为1的值*
// 10101010
//输出:10101010
WriteBit("&", n);
// 10101010
//&
// 01010101
//输出:0000000=0
n &= 0b01010101;
WriteBit("&", n);
n = 1 << 4;
//n=0b10000
//| 按位或,两个二进位只要有一个为1则为1,否则为0。*用来置1*
//n=0b00011
//输出100011
WriteBit("n", n);
n = n | 0b0011;
WriteBit("|", n);
n = 0b00001111;
//n=0b00001111
//^ 异或运算,不同为1,相同为0,*用来取反*
//n=0b00001001
//输出110
n = n ^ 0b1001;
WriteBit("^", n);
//n=0b0110
//^
//n=0b1001
//输出1111
n = n ^ 0b1001;
WriteBit("^", n);
//n=0000 0000 0000 0000 0000 0000 0000 1111
//~ 按位取反 如:101 取反为010
//输出1111 1111 1111 1111 1111 1111 1111 0000
n = 0b00001111;
n = ~n;
WriteBit("~", n);
}
// 1. 判断是否是偶数
static bool IsEven(uint n)
{
return (n & 1) == 0;//判断末位是否为0,true则是偶数
}
// 2. 利用Mask遮罩查看某一位的值,“1u << i”指定要操作的哪一位数(0开始计数),利用&实现遮罩取出只有1的位
static bool CheckBit(uint n, int i)
{
//u表示uint类型 例:CheckBit(65536, 15),查看65536右数第15位的值,返回false该值为0
//(65536 & 32768)
//0000 0000 0000 0001 0000 0000 0000 0000
//&
//0000 0000 0000 0000 1000 0000 0000 0000
//得:0000 0000 0000 0000 0000 0000 0000 0000
return (n & (1u << i)) != 0;}
// 3. 设置某一个bit为1,SetBit(8, 2)返回12
static uint SetBit(uint n, int i)
{
//ob1000
//|
//ob0100
//得:1100=12,即设置n右数2位为1(从0计位)
return n | (1u << i);}
// 4. 设置某一个bit为0,ClearBit(65536, 16)输出0
static uint ClearBit(uint n, int i)
{
uint mask = 0xffffffff;//16进制,代表二进制32个1
//(1u << 16)=65536
//mask=65536^65536=0
//n & mask=32个1 & 32个0=0
mask = mask ^ (1u << i);
return n & mask;}
// 5. 实际问题:IP普通形式与Uint的互转:1个uint=4个Byte(0~255)因此一个IP地址可以用一个uint表示
static string UInt2IP(uint ip)
{
//例子:UInt2IP(0x7F80FFFe);输出127.128.255.254
string IP = "";
uint n;
//0111 1111, 1000 0000, 1111 1111, 1111 1110。
n = ip >> 3*8;//取出首8位第1段IP:n=7F=127
IP += n + ".";
n = (ip >> 2*8) & 0xFF;//从7F80中利用&的遮罩取出末8位十六进制80,第二8位第2段IP:n=128
IP += n + ".";
n = ip >> 1*8 & 0xFF;//从7F80FF中利用&的遮罩取出末8位十六进制FF,第三8位第3段IP:n=255
IP += n + ".";
n = ip & 0xFF;//从7F80FFFE中利用&的遮罩取出末8位十六进制FE,最后8位为末段IP:n=254
IP += n;
return IP;
}
//将IP转为Unit格式,上面的反例:IP2Uint(127.128.255.254)
//返回0x7F80FFFe
static uint IP2Uint(string IP)
{
string[] array_ip = IP.Split('.');
uint ip = 0;
for (int i=0; i<array_ip.Length; i++)
{
uint n = uint.Parse(array_ip[i]);//将每段IP转换为uint格式
Console.WriteLine("左数第"+(i+1)+"段IP的unint值为:"+n);//127 128 255 254
n <<= (3 - i) * 8;//4段IP分别左移24、16、8、0位并累加在一起
ip += n;// 这里也可以写 ip |= n,因为4段IP值无交集;
}
return ip;
}
//计算一个整数的二进制表示里包含多少个1
static uint Count1(uint n)
{
//例:Count1(65535); 返回16
//例1:n=5=>101;
uint count = 0;
while (n > 0)
{
//n=5&4
//n=101 & 100=100=4,count=1
//n=100 & 011=0,count=2,跳出循环:5的二进制中包含2个1
//每计算一次减少n中的一个1,直至n中仅剩最高位的1(10000...) & 此时的n-1(01111....)得0,跳出循环.
//区别于遍历统计需要32次,此方法n有多少个1就执行多少次
n &= (n - 1);
count++;
}
return count;
}
//练习1:如何得到N个二进制1
static uint Print1(int n)
{
//方法1,此方法不能输出32个1,会返回0
//uint mask = 0xffffffff;
//return mask ^ (mask << n);
//方法2,此方法可以返回32个1
uint mask = 0xffffffff;
return mask = mask >> (32 - n);
}
//练习2:如何得到N个二进制1和(32-N)个0
static uint Print2(int n)
{
uint mask = 0xffffffff;
return mask = mask << (32 - n);
}
static void Main(string[] args)
{
Console.WriteLine("-------基础例子开始----------");
Test();
Console.WriteLine("=======基础例子结束==========");
uint n = 3;
Console.WriteLine(n << 2);
Console.WriteLine(IsEven(12));
Console.WriteLine(Count1(65535));
Console.WriteLine(CheckBit(65536, 15));
Console.WriteLine(SetBit(8, 2));
Console.WriteLine(ClearBit(65536, 16));
string IP = UInt2IP(0x7F80FFFe);
Console.WriteLine(IP);
uint ip = IP2Uint(IP);
Console.WriteLine("IP转换回uint: " + Convert.ToString(ip, 16));
Console.WriteLine("-------------练习1&2:如何得到N个二进制1-------------");
Console.WriteLine("请输入要返回的二进制个数:");
int a =Convert.ToInt32(Console.ReadLine());
//Console.WriteLine(Convert.ToString(Print1(a),2));//输出二进制结果
Console.WriteLine(Convert.ToString(Print2(a), 2));
Console.ReadKey();
}}}