Search code examples
c#stringxor

How to convert decimal to hexadecimal and XOR of the hex string


I have an array of string (string[]) as a decimal number like 0, 0, 4, 142, what I want to do is to convert that array to hexadecimal numbers like 0, 0, 4, 8e and perform an XOR in the C#, but I am not getting expected XOR,

Code:

public CheckSumHelper(string[] array)
{
  this._array = array.Select(x => Convert.ToInt64(x, 16)).ToArray();
}

public string GetCheckSum()
{
   long xor = this._array.Aggregate((x, y) => x ^ y);
   return xor.ToString("X");
}

Solution

  • Since 142 is a decimal (not hexadecimal) number (you don't treat 0x142 == 332), drop 16 in Convert.ToInt64(...):

     public static string GetCheckSum(string[] array) {
       // TODO: validate array here (it must be not null, not empty etc.)
    
       return array
         .Select(item => Convert.ToInt64(item)) // initial number is decimal           
         .Aggregate((s, item) => s ^ item) 
         .ToString("X");                        // we want final result being hexadecimal
     }
    

    And so you'll have 0 ^ 0 ^ 4 ^ 142 == 138 == 0x8A.

    Edit: When working with formats let computer explain what's going on:

    private static string GetCheckSumExplained(string test) {
      string[] array = test.Split(',');
    
      // Routine under test - GetCheckSum 
      string result = GetCheckSum(array);
      // Convert string back to long in order to represent it as binary and decimal
      long resultAsInt = Convert.ToInt64(result, 16);
    
      string args = string.Join(Environment.NewLine, array
        .Select(item => Convert.ToInt64(item))
        .Select(item => $"{Convert.ToString(item, 2).PadLeft(8, '0')} : {item,3} : 0x{item.ToString("X2")}"));
    
      return string.Join(Environment.NewLine, 
         args,
        "---------------------",
       $"{Convert.ToString(resultAsInt, 2).PadLeft(8, '0')} : {resultAsInt,3} : 0x{result.PadLeft(2, '0')}");
    }
    
    ...
    
    string test = "0,0,4,20,15,142,0,8,179,141,0, 8, 181, 141, 0,8"; 
    
    Console.Write(GetCheckSumExplained(test));
    

    Outcome:

    00000000 :   0 : 0x00
    00000000 :   0 : 0x00
    00000100 :   4 : 0x04
    00010100 :  20 : 0x14
    00001111 :  15 : 0x0F
    10001110 : 142 : 0x8E
    00000000 :   0 : 0x00
    00001000 :   8 : 0x08
    10110011 : 179 : 0xB3
    10001101 : 141 : 0x8D
    00000000 :   0 : 0x00
    00001000 :   8 : 0x08
    10110101 : 181 : 0xB5
    10001101 : 141 : 0x8D
    00000000 :   0 : 0x00
    00001000 :   8 : 0x08
    ---------------------
    10011111 : 159 : 0x9F
    

    So we have 9F. If you are sure that the right answer is B1 you should examine your data or/and formula

    Edit 2: If initial string looks like (see comments)

     00$00$04$20$15$8e$00$08$b3$8d$00$08$b5$8d$00$08
    

    we can implement GetCheckSum as

     // Now we're working with item_1$Item_2$...$Item_N
     public static string GetCheckSum(string value) {
       // TODO: Validate string here
    
       return value
         .Split('$')
         .Select(item => Convert.ToInt64(item, 16)) // 16 is required in this format
         .Aggregate((s, item) => s ^ item)
         .ToString("X");
     }
    
     ...
    
     string test = "00$00$04$20$15$8e$00$08$b3$8d$00$08$b5$8d$00$08";
    
     // Let's have a look on the the array
     Console.WriteLine(string.Join(", ", test
                       .Split('$')
                       .Select(item => Convert.ToInt64(item, 16))));
    
     Console.Wrire(GetCheckSum(test));
    

    Outcome:

     0, 0, 4, 32, 21, 142, 0, 8, 179, 141, 0, 8, 181, 141, 0, 8
     B1