We help IT Professionals succeed at work.

Calculating a 16 bit CheckSum

10,849 Views
Last Modified: 2013-12-17
Hi All,

I need to calculat a 16 bit checkSum(just the sum of bytes) the values that make up are all hex, this is what I have come up with;
string checkSum = (BitConverter.ToString(Encoding.ASCII.GetBytes(7B + 50 + 54  + 39 + 33 + 7D + 7B 7D)))
However I can not believe it is that easy. What am I missing.
Comment
Watch Question

If your checksum method is to just add up the bytes,
A. that is probably not a good checksum - if you want to avoid spurious collisions etc.
B. are you sure that the sum will never be more than 16bits?

Check this url for some algorithms: http://en.wikipedia.org/wiki/List_of_checksum_algorithms

- Ravs
Top Expert 2007

Commented:
This will give you a 16 bit Cyclic Redundancy Checksum if that's what you are after:

            private static ushort[] crc16_table = new ushort[8*32]
            {
                  0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
                  0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
                  0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
                  0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
                  0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
                  0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
                  0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
                  0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
                  0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
                  0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
                  0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
                  0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
                  0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
                  0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
                  0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
                  0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
                  0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
                  0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
                  0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
                  0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
                  0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
                  0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
                  0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
                  0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
                  0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
                  0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
                  0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
                  0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
                  0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
                  0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
                  0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
                  0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
            };
            
            public static ushort CRC16(string sInput)
            {
                  int i;
                  byte byAscVal;
                  ushort CRC = 0;
                  
                  string sPwd = sInput.ToUpper();
                  int iLen = sPwd.Length;
                  
                  for (i = 0; i < iLen; i++)
                  {
                        ushort CRCOld = CRC;
                        byAscVal = ASCIIEncoding.ASCII.GetBytes(sPwd.Substring(i, 1))[0];
                        CRC = (ushort)(( CRCOld >> 8) ^ crc16_table[byAscVal ^ (CRCOld & 0xff) ] );         
                  }
                  
                  return CRC;
            }

Author

Commented:
hi what is the difference between a 16bit checksum and 16 bit Cyclic Redundancy Checksum?
Top Expert 2007

Commented:
In a simple checksum, you are less likely to detect errors or changes that with a CRC. In the industry, the CRC is more commonly used.

Jim

Author

Commented:
Ok thanks.

In this cause I just need a 16bit checksum as that is what the device I am communicating with uses.
Top Expert 2007

Commented:
Be aware that you have to use the same method the device uses, or the communication will fail.

Jim

Author

Commented:
its is a sum of bytes (High byte first) but I don't know how to go about it.
Top Expert 2007

Commented:
When you say "the values that make up are all hex", do you mean you are getting them as a string? If so, what does it look like? If not, what exactly are you getting?

Author

Commented:
representation of the string that is to be used in the checksum
54 39 33 7D 7B 7D
Top Expert 2007

Commented:
So your string is like "54 39 33 7D 7B 7D"?
Top Expert 2007

Commented:
I have to run out and clean my gutters before it starts raining again - back in an hour or two...

Author

Commented:
lol no problem. yep thats the general format of the string, content will change though and there could be more characters
Top Expert 2007

Commented:
Two more questions:

1. For any given pair, say"7D", is that supposed to represent the hex value 0x7D, or do you want the ASCII values for "7" (0x37) and "D" (0x44) added to the checksum?

2. Does the value for space (0x20) get added, or is that just a spacer to throw away? Your example looks like that's just a delimiter, but I want to be sure.

Jim
Top Expert 2007

Commented:
Assuming the answer to the first question is 0x7D, and the the answer to the second is a delimiter, this will do what you want:

private bool GetChecksum(ref short checksum, string data)
{
   int byteCount = data.Length;
   int index = 0;
   char current;
   byte intOffset = 48;
   byte alphaOffset = 55;
   byte scale = 16;

   checksum = 0;
   if (byteCount < 2) // bad string
      return false;

   while (index < byteCount - 1)
   {
      current = data[index++];
      if (current < 'A')
      {
         checksum += (byte)(((byte)current - intOffset) * scale);
      }
      else
      {
         checksum += (byte)(((byte)current - alphaOffset) * 16);
      }
      current = data[index++];
      if (current < 'A')
      {
         checksum += (byte)(((byte)current - intOffset));
      }
      else
      {
         checksum += (byte)(((byte)current - alphaOffset));
      }
      index++;
   }
   return true;
}

Author

Commented:
Yes the space is a delimiter and hence is not included in the checksum, can I ask what the difference is between 0x7D and 7D.
Top Expert 2007

Commented:
If you look in the table for the CRC above, you will see that's how hex values are specified in C#.

Author

Commented:
ahh I see does this effect the final calcalation though as I think the 0x is ommitted
Top Expert 2007

Commented:
I took that into account in the code I posted above.

Author

Commented:
o Brill,

One last question Jim, could you step through the code?
Top Expert 2007

Commented:
I ran the code - it ran fine. Did you have trouble with it?

Author

Commented:
No sorry its fine ... just wanted an explanation so that I understand it a bit better
Top Expert 2007
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.