C#的常见几种位操作运算,与($)、或(|)、非(~)、异或(^)、左移(<<)、右移(>>)

位操作一般来说比加减乘除计算要快一些

与(&)操作符

与(&)操作符的位都为1时,才为1,其他都为0,因此与(&)操作符的结果范围在[0, Math.Min(x,y)],x,y均为正整数

或(|)操作符

或(|)操作符的位都为0时,才为0,其他都为1,因此或(|)操作符的结果范围在[Math.Max(x,y), x+y],x,y均为正整数

非(~)操作符

非(~)操作符按位取反,1转化为0, 0转化为1,因此非(~)操作符满足[x+~x=-1]一个数与其取反操作之和为-1

异或(^)操作符

异或(^)操作符的位不同时为1, 位相同时为0

左移(<<)操作符

左移(<<)操作符:【最左侧位不要,在最右侧补0】,相当于乘以2个N次方,【移位是除以32后的余数,范围[0,31],即以32为一个周期】

右移(>>)操作符

右移(>>)操作符:【最右侧位不要,在最左侧补符号位。(正数补0,负数补1)】,相当于除以2个N次方,【移位是除以32后的余数,范围[0,31],即以32为一个周期】

C#新建控制台应用程序BitOperationDemo。

相关测试程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace BitOperationDemo
{
    class Program
    {
        /// <summary>
        /// 标识符字典
        /// </summary>
        static readonly Dictionary<OperationSymbol, string> dict = new Dictionary<OperationSymbol, string>()
        {
            { OperationSymbol.AND,"与(&)"},{ OperationSymbol.OR,"或(|)"},{ OperationSymbol.NOT,"非(~)"},{ OperationSymbol.XOR,"异或(^)"},
            { OperationSymbol.SHIFT_LEFT,"左移(<<)"},{ OperationSymbol.SHIFT_RIGHT,"右移(>>)"}
        };
        static void Main(string[] args)
        {
            Console.SetWindowSize(120, 50);
            Console.WriteLine($"与(&)操作符的位都为1时,才为1,其他都为0,因此与(&)操作符的结果范围在[0, Math.Min(x,y)],x,y均为正整数");
            Console.WriteLine($"或(|)操作符的位都为0时,才为0,其他都为1,因此或(|)操作符的结果范围在[Math.Max(x,y), x+y],x,y均为正整数");
            Console.WriteLine($"非(~)操作符按位取反,1转化为0, 0转化为1,因此非(~)操作符满足[x+~x=-1]一个数与其取反操作之和为-1");
            Console.WriteLine($"异或(^)操作符的位不同时为1, 位相同时为0");
            Console.WriteLine($"左移(<<)操作符:【最左侧位不要,在最右侧补0】,相当于乘以2个N次方,【移位是除以32后的余数,范围[0,31],即以32为一个周期】");
            Console.WriteLine($"右移(>>)操作符:【最右侧位不要,在最左侧补符号位。(正数补0,负数补1)】,相当于除以2个N次方,【移位是除以32后的余数,范围[0,31],即以32为一个周期】");
            Console.WriteLine();
            int x = 12345;
            int y = 34567;//34567除以32,余数为7,相当于移动7位
            string binaryX = Convert.ToString(x, 2).PadLeft(32, '0');
            string binaryY = Convert.ToString(y, 2).PadLeft(32, '0');
            Console.WriteLine($"整数【{x}】对应的32位二进制为【{binaryX}】");
            Console.WriteLine($"整数【{y}】对应的32位二进制为【{binaryY}】");
            Console.WriteLine("-----------------下面分别用二进制字符串逻辑处理 以及 系统内置的操作符进行操作计算-----------------");

            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.AND);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.OR);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.NOT);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.XOR);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.SHIFT_LEFT);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.SHIFT_RIGHT);

            Console.WriteLine("-----------------下面测试负数进行操作计算-----------------");
            x = -12345;
            binaryX = Convert.ToString(x, 2).PadLeft(32, '0');
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.AND);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.OR);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.NOT);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.XOR);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.SHIFT_LEFT);
            PrintOperatorResult(x, y, binaryX, binaryY, OperationSymbol.SHIFT_RIGHT);
            Console.ReadLine();
        }

        /// <summary>
        /// 打印结果比较
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="binaryX"></param>
        /// <param name="binaryY"></param>
        /// <param name="operationSymbol"></param>
        static void PrintOperatorResult(int x, int y, string binaryX, string binaryY, OperationSymbol operationSymbol)
        {
            string binaryResult = GetOperatorResult(binaryX, binaryY, operationSymbol);
            int result = 0;
            switch (operationSymbol)
            {
                case OperationSymbol.AND:
                    result = x & y;
                    break;
                case OperationSymbol.OR:
                    result = x | y;
                    break;
                case OperationSymbol.NOT:
                    result = ~x;
                    break;
                case OperationSymbol.XOR:
                    result = x ^ y;
                    break;
                case OperationSymbol.SHIFT_LEFT:
                    result = x << y;
                    break;
                case OperationSymbol.SHIFT_RIGHT:
                    result = x >> y;
                    break;
            }
            Console.WriteLine($"{dict[operationSymbol]}操作符系统内置的操作符运算结果为【{result}】,使用二进制字符串还原后的整数结果为【{Convert.ToInt32(binaryResult, 2)}】");
            Console.WriteLine();
        }

        /// <summary>
        /// 获取操作符的结果
        /// </summary>
        /// <param name="binaryX">32位二进制字符串,第一个数</param>
        /// <param name="binaryY">32位二进制字符串,第二个数</param>
        /// <param name="operationSymbol">指定的操作符枚举</param>
        /// <returns></returns>
        static string GetOperatorResult(string binaryX, string binaryY, OperationSymbol operationSymbol)
        {
            string result = string.Empty;
            switch (operationSymbol)
            {
                case OperationSymbol.AND:
                    result = CalculateOperatorResult(binaryX, binaryY, (left, right) => (left == '1' && right == '1') ? "1" : "0");
                    break;
                case OperationSymbol.OR:
                    result = CalculateOperatorResult(binaryX, binaryY, (left, right) => (left == '0' && right == '0') ? "0" : "1");
                    break;
                case OperationSymbol.NOT:
                    result = CalculateOperatorResult(binaryX, binaryY, (left, right) => (left == '0') ? "1" : "0");
                    break;
                case OperationSymbol.XOR:
                    result = CalculateOperatorResult(binaryX, binaryY, (left, right) => (left == right) ? "0" : "1");
                    break;
                case OperationSymbol.SHIFT_LEFT:
                    result = CalculateShiftResult(binaryX, Convert.ToInt32(binaryY, 2), true);
                    break;
                case OperationSymbol.SHIFT_RIGHT:
                    result = CalculateShiftResult(binaryX, Convert.ToInt32(binaryY, 2), false);
                    break;
            }
            Console.WriteLine($"{dict[operationSymbol]}操作符逻辑运算的32位二进制结果为【{result}】");
            return result;
        }

        /// <summary>
        /// 计算逻辑运算的结果【与,或,非,异或】
        /// </summary>
        /// <param name="binaryX">32位二进制字符串,第一个数</param>
        /// <param name="binaryY">32位二进制字符串,第二个数</param>
        /// <param name="logicOperator">逻辑操作委托</param>
        /// <returns></returns>
        static string CalculateOperatorResult(string binaryX, string binaryY, Func<char, char, string> logicOperator)
        {
            string result = string.Empty;
            for (int i = 0; i < 32; i++)
            {
                result += logicOperator(binaryX[i], binaryY[i]);
            }
            return result;
        }

        /// <summary>
        /// 计算移位操作【左移,右移】
        /// </summary>
        /// <param name="binaryX"></param>
        /// <param name="shiftCount">移动几位,该数需要转化为【除以32的余数】</param>
        /// <param name="leftShift">true代表左移,false代表右移</param>
        /// <returns></returns>
        static string CalculateShiftResult(string binaryX, int shiftCount, bool leftShift)
        {
            //比如移动32位,就相当于移动0位,移动33位,就相当于移动1位【32位作为一个周期】
            shiftCount = (int)((uint)shiftCount % 32U);//确保余数在0~31之间波动
            if (leftShift)
            {
                //左移:【最左侧位不要,在最右侧补0】
                return binaryX.Remove(0, shiftCount).PadRight(32, '0');
            }
            else
            {
                //右移:【最右侧位不要,在最左侧补符号位。(正数补0,负数补1)】
                return binaryX.Remove(32 - shiftCount, shiftCount).PadLeft(32, binaryX[0]);
            }
        }
    }

    /// <summary>
    /// 操作符号,运算符号
    /// </summary>
    enum OperationSymbol
    {
        /// <summary>
        /// 与 【位都是1时结果为1,否则为0】
        /// </summary>
        AND = 0,
        /// <summary>
        /// 或 【位都是0时结果为0,否则为1】
        /// </summary>
        OR = 1,
        /// <summary>
        /// 非 【位取反】,非操作只考虑第一个数
        /// </summary>
        NOT = 2,
        /// <summary>
        /// 异或 【位不同是为1,相同为0】
        /// </summary>
        XOR = 3,
        /// <summary>
        /// 左移,相当于乘以2个N次方【最左侧位不要,在最右侧补0】
        /// </summary>
        SHIFT_LEFT = 4,
        /// <summary>
        /// 右移,相当于除以2个N次方【最右侧位不要,在最左侧补符号位。(正数补0,负数补1)】
        /// </summary>
        SHIFT_RIGHT = 5
    }
}

程序运行如图:

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐