【方便查看】位运算的组合应用 一个int可以表示4个int
位运算是个很强大的东东,运用较多的地方可能就是组合了,枚举之类的。。
这里记录下 一个int包含4个不超过的256的值,并且还原的方法,
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Other{ class Other { /// <summary> /// 一个int 包含4组信息 /// </summary> /// <returns></returns> public void Merger() { string strR = string.Empty; //这里将32个0的组合拆分成8*4; 就是分成4组 可以包含4部分信息 //只有8位 所以 这个值不能超过2的8次方-1 256 当然 如果感觉 数字太小了 没关系 可以不均等分 或者int 改成long型就OK了 //0-8位第一组 //8-16位第一组 //16-24位第一组 //24-32位第一组 //00000000 00000000 00000000 00000000 // 110 210 88 99 //用一个int 表示 110 210 88 99 顺序不能乱,设计将这个int拆分成4个数字 int b4 = 110; int b3 = 210; int b2 = 88; int b1 = 99; int R = 0; //从低位到高位 //第一位 无所谓了 R = b1; //二进制码 //00000000 00000000 00000000 01100011 string sb = Convert.ToString(R, 2); int r2 = b2 << 8; //00000000 00000000 1011000 00000000 R = R + r2; //二进制码 //00000000 00000000 01011000 01100011 sb = Convert.ToString(R, 2); int r3 = b3 << 16; //00000000 11010010 00000000 00000000 sb = Convert.ToString(r3, 2); R = R + r3; //00000000 11010010 01011000 01100011 sb = Convert.ToString(R, 2); int r4 = b4 << 24; //01101110 00000000 00000000 00000000 sb = Convert.ToString(r4, 2); R = R + r4; //01101110 11010010 01011000 01100011 sb = Convert.ToString(R, 2); //总的来说其实就是 R = b1 + (b2 << 8) + (b3 << 16) + (b4 << 24); // R;这里的R 就是这4个数合成的一个数 下面 看拆分 //拆分需要从高位到低位 int OldR = R; r4 = R >> 24;//b4 sb = Convert.ToString(r4, 2); //01101110 r3 = r4 << 24; //将r4左移24 变为了 //01101110 00000000 00000000 00000000 r3 = R - r3;//R-(r4>>24) //01101110 11010010 01011000 01100011 //- //01101110 00000000 00000000 00000000 //= //00000000 11010010 01011000 01100011 r3 = r3 >> 16;//右移16位 //11010010 也就是210 sb = Convert.ToString(r3, 2); r2 = R - (r4 << 24) - (r3 << 16); r2 = r2 >> 8;//88 int r1 = R - (r4 << 24) - (r3 << 16) - (r2 << 8); //拆分完毕 } /* 说明: === 1. and运算 === and运算通常用于二进制取位操作,例如一个数 and 1的结果就是取二进制的最末位。 * 这可以用来判断一个整数的奇偶,二进制的最末位为0表示该数为偶数,最末位为1表示该数为奇数。 * 相同位的 * 两个数字都为1,则为1;若有一个不为1,则为0。 * 00111 * 11100 * (&;或者and) * ---------------- 00100 === 2. or运算 === or运算通常用于二进制特定位上的无条件赋值,例如一个数or 1的结果就是把二进制最末位强行变成1。 * 如果需要把二进制最末位变成0, * 对这个数or 1之后再减一就可以了,其实际意义就是把这个数强行 * 变成最接近的偶数。 相同位只要一个为1即为1。 * 00111 * 11100 * (|或者or) * ---------------- * 11111 === 3. xor运算 === 异或的符号是⊕。 xor运算通常用于对二进制的特定一位进行取反操作,因为异或可以这样定义:0和1异或0都不变,异或1则取反。 * xor运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变,即(a xor b) xor b = a。xor运算可以用于简单的加密, * 比如我想对我MM说1314520,但怕别人知道,于是双方约定拿我的生日19880516作为密钥。1314520 xor 19880516 = 20665500, * 我就把20665500告诉MM。MM再次计算20665500 xor 19880516的值,得到1314520,于是她就明白了我的企图。 * 相同位不同则为1,相同则为0。 * 00111 * 11100 * (^或者xor) * ---------------- * 11011 * * === 4. not运算 === not运算的定义是把内存中的0和1全部取反。使用not运算时要格外小心,你需要注意整数类型有没有符号。 * 如果not的对象是无符号整数(不能表示负数),那么得到的值就是它与该类型上界的差,因 * 为无符号类型的数是用00到$FFFF依次表示的。下面的两个程序(仅语言不同)均返回65435。 * * === 5. shl运算 === a shl b就表示把a转为二进制后左移b位(在后面添b个0)。 * 例如100的二进制为1100100,而110010000转成十进制是400, * 那么100 shl 2 = 400。可以看出,a shl b的值实际上就是a乘以2的b次方, * 因为在二进制数后添一个0就相当于该数乘以2。 通常认为a shl 1比a * * 2更快,因为前者是更底层一些的操作。因此程序中乘以2的操作请尽量用左移一位来代替。 * 定义一些常量可能会用到shl运算。你可以方便地用1 shl 16 - 1来表示65535。 * 很多算法和数据结构要求数据规模必须是2的幂,此时可以用shl来定义Max_N等常量。 * * * === 6. shr运算 === 和shl相似,a shr b表示二进制右移b位(去掉末b位),相当于a除以2的b次方(取整)。 * 我们也经常用shr 1来代替div 2,比如二分查找、堆的插入操作等等。想办法用shr代替除法运算 * 可以使程序效率大大提高。最大公约数的二进制算法用除以2操作来代替慢得出奇的mod运算,效率可以提高60%。 */ /* 应用举例 (1) 判断int型变量a是奇数还是偶数 a&1 = 0 偶数 a&1 = 1 奇数 (2) 取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1 (3) 将int型变量a的第k位清0,即a=a&~(1 < <k) (4) 将int型变量a的第k位置1, 即a=a|(1 < <k) (5) int型变量循环左移k次,即a=a < <k|a>>16-k (设sizeof(int)=16) (6) int型变量a循环右移k次,即a=a>>k|a < <16-k (设sizeof(int)=16) (7)整数的平均值 对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法: int average(int x, int y) //返回X,Y 的平均值 { return (x&y)+((x^y)>>1); } (8)判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂 boolean power2(int x) { return ((x&(x-1))==0)&&(x!=0); } (9)不用temp交换两个整数 void swap(int x , int y) { x ^= y; y ^= x; x ^= y; } (10)计算绝对值 int abs( int x ) { int y ; y = x >> 31 ; return (x^y)-y ; //or: (x+y)^y } (11)取模运算转化成位运算 (在不产生溢出的情况下) a % (2^n) 等价于 a & (2^n - 1) (12)乘法运算转化成位运算 (在不产生溢出的情况下) a * (2^n) 等价于 a < < n (13)除法运算转化成位运算 (在不产生溢出的情况下) a / (2^n) 等价于 a>> n 例: 12/8 == 12>>3 (14) a % 2 等价于 a & 1 (15) if (x == a) x= b; else x= a; 等价于 x= a ^ b ^ x; (16) x 的 相反数 表示为 (~x+1) */ /* int a = 2 + 4 + 8 + 16;=30 int t = a & 8;=30 int t2 = a | 8;=8 int t3 = a ^ 8;=20 a = 2; int b = 3; a = a ^ b; b = a ^ b; a = a ^ b; string s = Convert.ToString(32, 2);//二进制表示方法 */ }}