首页 > 解决方案 > C#中二进制值之间的异或运算

问题描述

我的问题是我有一个二进制字符串列表,如下所示:

列表=<"1111","1010","1010","0011">

和一个二进制值 st1=1010 的输入字符串。我想在以下之间进行异或:

st3=st1 异或列表<0>

然后 :

st3=st3 异或列表<1>

st3=st3Xor 列表 <2>;

st3=st3 Xor 列表 <3>;

其中操作将是 st1 Xor 与键列表中的第一个键,结果 Xor 与键列表中的第二个键,结果 Xor 与键列表中的第三个键,依此类推。任何人都可以帮助我吗?我已经尝试过这段代码,但它没有像我预期的那样工作:

foreach (string k in keys)
        {
            string st1 = textBox1.text;
            string st2 = k;
            string st3;
            st3 = "";
        //i wanted to make the length of both strings st1 and st2 equal
        //here if the length of st1 greater than st2 
        if (st1.Length > st2.Length)
        {
            int n = st1.Length - st2.Length;
            string pad = "";
            for (int j = 1; j <= n; j++)
            { pad += 0; }
            string recover = pad.ToString() + st2;
           //this is my Xor operation that i made for string values  
            for (int counter = 0; counter < st1.Length; counter++)
            {
                if (st1[counter] != recover[counter])
                {
                    st3 = st3 + '1';
                }
                else
                { st3 = st3 + '0'; }


            }
            listBox4.Items.Add("Xor :" + st3.ToString());
        }
        //here if st1 is less than st2
        else if (st1.Length < st2.Length)
        {
            int nn = st2.Length - st1.Length;

            string ppad = "";
            for (int j = 1; j <= nn; j++)
            {
                ppad += 0;
            }

            string recover = ppad.ToString() + st1;

            for (int counter = 0; counter < st2.Length; counter++)
            {
                if (st2[counter] != recover[counter])
                {
                    st3 = st3 + '1';

                }
                else
                { st3 = st3 + '0'; }

                }
            listBox4.Items.Add("Xor :" + st3.ToString());}
        //here if st1 equal st2
         else
        {
            for (int counter = 0; counter < st1.Length; counter++)
            {
                if (st1[counter] != st2[counter])
                {
                    st3 = st3 + '1';

                }
                else
                { st3 = st3 + '0'; }

            }
            listBox4.Items.Add("Xor :" + st3.ToString()); 
        }
            }

我没想到的结果是: 在此处输入图像描述

标签: c#xor

解决方案


这是一种方法(任意长度的二进制字符串):

  • 将字符串转换回整数BigIntegers,这样我们就可以真正得到现有按位异或运算符 ( ^) 的效用。
  • 使用 LINQ 的 Aggregate 将种子值 (st1) 与使用 Xor 转换的列表连续左折叠。
  • 由于您似乎只对最低 4 位感兴趣,因此我应用了一个掩码,尽管如果您的所有数字都是严格的 4 位,这实际上不是必需的(因为 0 Xor 0 保持为 0)
  • 您可以将 int 转换回二进制字符串,Convert.ToString(x, 2)然后使用 PadLeft 替换任何丢失的前导零。

编辑- OP 已经从一个示例 4 位数更改了问题,现在要求是使用任意长度的二进制字符串。这种方法仍然有效,但我们需要使用BigInteger(它仍然有一个XOR^ 运算符),但我们需要帮助器来解析和格式化二进制字符串,因为这些不是内置在BigInteger. BitMask 和填充也已被删除,因为字符串不是固定长度的 - 结果最多有 1 个前导零:

var list = new List<string>{"10101010101010101101","1101010101010101011",
  "1110111111010101101","11111111111111111111111111","10101010110101010101"};
var listNum = list.Select(l =>  BinaryStringToBigInteger(l));

var st1 = "000000001";
var seedNumber = BinaryStringToBigInteger(st1);

var chainedXors = listNum.Aggregate(seedNumber, (prev, next) => prev ^ next);
// Back to binary representation of the string
var resultString = chainedXors.ToBinaryString();

而且因为没有原生支持将 BigIntegers 转换为二进制字符串/从二进制字符串转换,所以您需要一个转换助手,例如Douglas 的助手:

BigInteger BinaryStringToBigInteger(string binString)
{
    return binString.Aggregate(BigInteger.Zero, (prev, next) => prev * 2 + next - '0');
}

而对于反向操作,ToBinaryString就是来自这个helper

32 位整数答案

如果二进制字符串为 32 位或更少,则存在更简单的解决方案,因为存在与二进制字符串的开箱即用转换。同样的方法应该适用于 64 位长。

var list = new List<string>{"1111","1010","1010","0011","0011"};
var listNum = list.Select(l =>  Convert.ToInt32(l, 2));
// If you only want the last 4 bits. Change this to include as many bits as needed.
var bitMask = Convert.ToInt32("00000000000000000000000000001111", 2);

var st1 = "1010";
var someNum = Convert.ToInt32(st1, 2);

var chainedXors = listNum.Aggregate(someNum, (prev, next) => prev ^ next);
// If you need the result back as a 4 bit binary-string, zero padded
var resultString = Convert.ToString(chainedXors & bitMask, 2)
                          .PadLeft(4, '0');

推荐阅读