C#运算符之与,或,异或及移位运算

203 篇文章 0 订阅
61 篇文章 3 订阅

C#运算符之与,或,异或及移位运算

1.剖析异或运算(^)

二元 ^ 运算符是为整型和 bool 类型预定义的。对于整型,^ 将计算操作数的按位“异或”。对于 bool 操作数,^ 将计算操作数的逻辑“异或”;也就是说,当且仅当只有一个操作数为 true 时,结果才为 true。

数值运算举例

按位异或的3个特点:
(1) 0^0=0,0^1=1  0异或任何数=任何数
(2) 1^0=1,1^1=0  1异或任何数-任何数取反
(3) 1^1=0,0^0=0  任何数异或自己=把自己置0

例如:10100001^00010001=10110000


按位异或的几个常见用途:

(1) 使某些特定的位翻转
    例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。
       10100001^00000110 = 10100111

(2) 实现两个值的交换,而不必使用临时变量。
    例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:
    a = a^b;   //a=10100111
    b = b^a;   //b=10100001
    a = a^b;   //a=00000110

(3) 在汇编语言中经常用于将变量置零:
    xor   a,a

(4) 快速判断两个值是否相等
    举例1: 判断两个整数a,b是否相等,则可通过下列语句实现:
        return ((a ^ b) == 0)
   
    举例2: Linux中最初的ipv6_addr_equal()函数的实现如下:
    static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
    {
        return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
            a1->s6_addr32[1] == a2->s6_addr32[1] &&
            a1->s6_addr32[2] == a2->s6_addr32[2] &&
            a1->s6_addr32[3] == a2->s6_addr32[3]);
    }
   
    可以利用按位异或实现快速比较, 最新的实现已经修改为:
    static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
    {
    return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
        (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
        (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
        (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
    }


2 & 运算符(与)

1 & 0 为0
0 & 0 为0
1 & 1 为1

3 | 运算符(或)

1 | 0 为1
0 | 0 为0
1 | 1 为1

------------------

C#移位运算(左移和右移)

 


  C#是用<<(左移) 和 >>(右移) 运算符是用来执行移位运算。

  左移 (<<)

  将第一个操作数向左移动第二个操作数指定的位数,空出的位置补0。
  左移相当于乘. 左移一位相当于乘2;左移两位相当于乘4;左移三位相当于乘8。

  x<<1= x*2
  x<<2= x*4
  x<<3= x*8
  x<<4= x*16

  同理, 右移即相反:

  右移 (>>)
  将第一个操作数向右移动第二个操作数所指定的位数,空出的位置补0。

  右移相当于整除. 右移一位相当于除以2;右移两位相当于除以4;右移三位相当于除以8。

  x>>1= x/2
  x>>2= x/4
  x>>3= x/8
  x>>4=x/16


 int i = 7;
 int j = 2;
 Console.WriteLine(i >> j);   //输出结果为1


  当声明重载C#移位运算符时,第一个操作数的类型必须总是包含运算符声明的类或结构,并且第二个操作数的类型必须总是 int,如:

class Program   
{       
 static void Main(string[] args)       
 {           
  ShiftClass shift1 = new ShiftClass(5, 10);           
  ShiftClass shift2 = shift1 << 2;           
  ShiftClass shift3 = shift1 >> 2;           
  Console.WriteLine("{0} << 2 结果是:{1}", shift1.valA,  shift2.valA);           
  Console.WriteLine("{0} << 2 结果是:{1}", shift1.valB,shift2.valB);           
  Console.WriteLine("{0} >> 2 结果是:{1}", shift1.valA,  shift3.valA);           
  Console.WriteLine("{0} >> 2 结果是:{1}", shift1.valB, shift3.valB);           
  Console.ReadLine();       
 }       
 public class ShiftClass       
 {          
  public int valA;          
  public int valB;           
  public ShiftClass(int valA, int valB)           
  {               
   this.valA = valA;               
   this.valB = valB;           
  }           
  public static ShiftClass operator <<(ShiftClass shift, int count)           
  {               
   int a = shift.valA << count;               
   int b = shift.valB << count;               
   return new ShiftClass(a, b);           
  }           
  public static ShiftClass operator >>(ShiftClass shift, int count)           
  {               
   int a = shift.valA >> count;               
   int b = shift.valB >> count;               
   return new ShiftClass(a, b);           
  }       
 }   
}

因为位移比乘除速度快.对效率要求高,而且满足2的幂次方的乘除运方,可以采用位移的方式进行。

位运算的例子

获取某个数的二进制数的某位上的值 1 or 0
设置某个数的二进制数的某位上的值 1 or 0

/// <summary>
        /// 获取某个数的二进制数的某位上的值 1 or 0
        /// </summary>
        /// <param name="iValue">原数</param>
        /// <param name="iPosition">要取的位数,从左开始 第一个为第一位</param>
        /// <returns>1 or 0</returns>
        public static int GetPositionNValue(int iValue,int iPosition)
        {
            if (iPosition < 1)
                iPosition = 1;
            int k = 1 << iPosition-1;
            if ((iValue & k) == k)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 设置某个数的二进制数的某位上的值 1 or 0
        /// </summary>
        /// <param name="iValue">原数</param>
        /// <param name="iPosition">要设置的位数,从左开始 第一个为第一位</param>
        /// <param name="iPositionValue">某位上要设置的值0 or 1</param>
        /// <returns>1 or 0</returns>
        public static int SetPositionNValue(int iValue, int iPosition,int iPositionValue)
        {
            //某位置0: 按位& 1111110111……, 0的位置为想要置0的所在数的位置.
            //某位置1: 按位|  0000001000……, 1的位置为想要置1的所在数的位置.

            //if (iPosition < 1)
            //    iPosition = 1;
            //if (iPositionValue != 0)
            //    iPositionValue = 1;
            //if (iPositionValue > 0)
            //{
            //    int k = 1 << iPosition - 1;
            //    var newVal = iValue | k;
            //    return newVal;
            //}
            //else
            //{
            //  //未实现
            //}

            if (iPosition < 1)
                iPosition = 1;
            if (iPositionValue != 0)
                iPositionValue = 1;
            var tempValue = 1 << iPosition - 1;
            if (iPositionValue == 0)
            {
                if ((iValue & tempValue) == 0)
                {
                    return iValue;
                }
                else
                {
                    return iValue - tempValue;
                }
            }
            else
            {
                if ((iValue & tempValue) == 0)
                {
                    return iValue + tempValue; ;
                }
                else
                {
                    return iValue;
                }
            }
        }
附单元测试代码
[Test()]
        public void SetPositionNValueTest()
        {
            //第i位是否为1,i从0开始。
            var i = MathHelper.SetPositionNValue(0, 1, 1);
            Assert.IsTrue(i == 1);
            i = MathHelper.SetPositionNValue(0, 2, 1);
            Assert.IsTrue(i == 2);
            i = MathHelper.SetPositionNValue(0, 3, 1);
            Assert.IsTrue(i == 4);

            i = MathHelper.SetPositionNValue(1, 1, 1);
            Assert.IsTrue(i == 1);
            i = MathHelper.SetPositionNValue(1, 2, 1);
            Assert.IsTrue(i == 3);
            i = MathHelper.SetPositionNValue(1, 3, 1);
            Assert.IsTrue(i == 5);

            i = MathHelper.SetPositionNValue(2, 1, 1);
            Assert.IsTrue(i == 3);
            i = MathHelper.SetPositionNValue(2, 2, 1);
            Assert.IsTrue(i == 2);
            i = MathHelper.SetPositionNValue(2, 3, 1);
            Assert.IsTrue(i == 6);

            i = MathHelper.SetPositionNValue(3, 1, 1);
            Assert.IsTrue(i == 3);
            i = MathHelper.SetPositionNValue(3, 2, 1);
            Assert.IsTrue(i == 3);
            i = MathHelper.SetPositionNValue(3, 3, 1);
            Assert.IsTrue(i == 7);

            i = MathHelper.SetPositionNValue(4, 1, 1);
            Assert.IsTrue(i == 5);
            i = MathHelper.SetPositionNValue(4, 2, 1);
            Assert.IsTrue(i == 6);
            i = MathHelper.SetPositionNValue(4, 3, 1);
            Assert.IsTrue(i == 4);

            i = MathHelper.SetPositionNValue(5, 1, 1);
            Assert.IsTrue(i == 5);
            i = MathHelper.SetPositionNValue(5, 2, 1);
            Assert.IsTrue(i == 7);
            i = MathHelper.SetPositionNValue(5, 3, 1);
            Assert.IsTrue(i == 5);

            i = MathHelper.SetPositionNValue(6, 1, 1);
            Assert.IsTrue(i == 7);
            i = MathHelper.SetPositionNValue(6, 2, 1);
            Assert.IsTrue(i == 6);
            i = MathHelper.SetPositionNValue(6, 3, 1);
            Assert.IsTrue(i == 6);

            i = MathHelper.SetPositionNValue(7, 1, 1);
            Assert.IsTrue(i == 7);
            i = MathHelper.SetPositionNValue(7, 2, 1);
            Assert.IsTrue(i == 7);
            i = MathHelper.SetPositionNValue(7, 3, 1);
            Assert.IsTrue(i == 7);

            //set 0
            i = MathHelper.SetPositionNValue(1, 1, 0);
            Assert.IsTrue(i == 0);
            i = MathHelper.SetPositionNValue(1, 2, 0);
            Assert.IsTrue(i == 1);
            i = MathHelper.SetPositionNValue(1, 3, 0);
            Assert.IsTrue(i == 1);

            i = MathHelper.SetPositionNValue(2, 1, 0);
            Assert.IsTrue(i == 2);
            i = MathHelper.SetPositionNValue(2, 2, 0);
            Assert.IsTrue(i == 0);
            i = MathHelper.SetPositionNValue(2, 3, 0);
            Assert.IsTrue(i == 2);

            i = MathHelper.SetPositionNValue(3, 1, 0);
            Assert.IsTrue(i == 2);
            i = MathHelper.SetPositionNValue(3, 2, 0);
            Assert.IsTrue(i == 1);
            i = MathHelper.SetPositionNValue(3, 3, 0);
            Assert.IsTrue(i == 3);

            i = MathHelper.SetPositionNValue(4, 1, 0);
            Assert.IsTrue(i == 4);
            i = MathHelper.SetPositionNValue(4, 2, 0);
            Assert.IsTrue(i == 4);
            i = MathHelper.SetPositionNValue(4, 3, 0);
            Assert.IsTrue(i == 0);

            i = MathHelper.SetPositionNValue(5, 1, 0);
            Assert.IsTrue(i == 4);
            i = MathHelper.SetPositionNValue(5, 2, 0);
            Assert.IsTrue(i == 5);
            i = MathHelper.SetPositionNValue(5, 3, 0);
            Assert.IsTrue(i == 1);

            i = MathHelper.SetPositionNValue(6, 1, 0);
            Assert.IsTrue(i == 6);
            i = MathHelper.SetPositionNValue(6, 2, 0);
            Assert.IsTrue(i == 4);
            i = MathHelper.SetPositionNValue(6, 3, 0);
            Assert.IsTrue(i == 2);

            i = MathHelper.SetPositionNValue(7, 1, 0);
            Assert.IsTrue(i == 6);
            i = MathHelper.SetPositionNValue(7, 2, 0);
            Assert.IsTrue(i == 5);
            i = MathHelper.SetPositionNValue(7, 3, 0);
            Assert.IsTrue(i == 3);

        }



--- end ---

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值