safaa
safaa

Reputation: 57

Xor operation between binary values in C#

My question is that i have a list of binary string like below :

list=<"1111","1010","1010","0011">

and an input string of binary value st1=1010. I want to Xor between :

st3=st1 Xor list<0>

then :

st3=st3 Xor list<1>

st3=st3Xor list <2>;

st3=st3 Xor list <3>;

where the operation will be st1 Xor with first key in keys list and the result Xor with the second key in keys list and the result Xor with the third key in keys list and so on . Can any one help me please? i have tried this code but it does not work as i expected :

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()); 
        }
            }

the result that i do not expected is : enter image description here

Upvotes: 0

Views: 2020

Answers (3)

StuartLC
StuartLC

Reputation: 107237

Here's one approach (Arbitrary length binary strings):

  • Convert the strings back to integers BigIntegers, so that we can actually get the utility of existing bitwise Xor operator (^).
  • Use LINQ's Aggregate to consecutively left-fold the seed value (st1) with the converted list with Xor.
  • Since you seem interested only in the lowest 4 bits, I've applied a mask, although if all your numbers are strictly 4 bits, this isn't actually necessary (since 0 Xor 0 stays 0)
  • You can convert the int back to a binary string with Convert.ToString(x, 2) and then PadLeft to replace any missing leading zeroes.

Edit - OP has changed the question from an example 4 bit number and the requirement is now to work with arbitrary length binary strings. This approach still works, but we'll need to use BigInteger (which still has an XOR ^ operator), but we need helpers to parse and format binary strings, as these aren't built into BigInteger. The BitMask and padding have also been removed, since the strings aren't fixed length - the result will have at most 1 leading zero:

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();

And because there's no native support for converting BigIntegers to / from binary strings, you'll need a conversion helper such as Douglas's one here:

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

And for the reverse operation, ToBinaryString is from this helper.

32 Bit Integer answer

If the Binary strings are 32 bits or less, then a much simpler solution exists, since there are out of the box conversions to / from binary strings. The same approach should apply for 64 bit longs.

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');

Upvotes: 2

Michał Turczyn
Michał Turczyn

Reputation: 37347

Try this code:

static void Main(string[] args)
{
    List<string> list = new List<string> { "1111", "1010", "1010", "0011" };
    string st1 = "1010";

    foreach (string item in list)
    {
        st1 = XorBins(st1, item);
        Console.WriteLine(st1);
    }
    Console.ReadKey();
}

private static string XorBins(string bin1, string bin2)
{
    int len = Math.Max(bin1.Length, bin2.Length);
    string res = "";
    bin1 = bin1.PadLeft(len, '0');
    bin2 = bin2.PadLeft(len, '0');

    for (int i = 0; i < len; i++)
        res += bin1[i] == bin2[i] ? '0' : '1';

    return res;
}

Upvotes: 1

Sweeper
Sweeper

Reputation: 270980

Here is an Xor method for you:

public static string Xor(string s1, string s2) {
    // find the length of the longest of the two strings
    int longest = Math.Max(s1.Length, s2.Length);

    // pad both strings to that length. You don't need to write the padding
    // logic yourself! There is already a method that does that!
    string first = s1.PadLeft(longest, '0');
    string second = s2.PadLeft(longest, '0');

    // Enumerable.Zip takes two sequences (in this case sequences of char, aka strings)
    // and lets you transform each element in the sequences. Here what 
    // I did was check if the two chars are not equal, in which case
    // I transform the two elements to a 1, 0 otherwise
    return string.Join("", Enumerable.Zip(first, second, (x, y) => x != y ? '1' : '0'));
}

You can use it like this:

Xor("1111", "1010") // 0101

Upvotes: 1

Related Questions