简体   繁体   中英

Checksum calculation in android/java

I wrote a checksum calculation function in android/java. the function as follows

void CalculateCheckSum( byte[] bytes ){
     short CheckSum = 0, i = 0;
     for( i = 0; i < bytes.length; i++ ){
        CheckSum = (short) ((short)CheckSum + (short)bytes[i]);
     }

     Log.i("Checksum", Integer.toHexString(CheckSum));
}

input values for calculation of checksum are 0xEF, 0x01, 0xEF, 0x01, 0x33, 0x0C, 0xB8, 0xE5, 0xFC, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF. I manually calculated the checksum value and result is 0xCE4. When using the above function i get answer as 0xFFFFFFE4. Is any error in my calculation, if yes then please correct me.

thanks

Use a debugger and debug your code. Generally though, if you keep adding stuff up, even if you use an int or a long , it is bound to overflow at some point, so you will get unexpected results. Best to use a standard checksum algorithm or one of the already available classes such as CRC32 or Adler31 . As for your code, you seem to be treating the result as an integer, so why cast to short in the first place?

Java does all arithmetic calculations using int 's, so your byte s get converted to int and the ones that don't fit into a byte will look like this as int 's: ffffffef (-17). Naturally you only need the actual byte value, so you need to zero out everything else using (0xff & b) . So your loop than becomes something like this:

  int checkSum = 0;

  for(byte b : bytes){
    checkSum += (0xff & b);
  }

The problem here is the (short) cast of bytes[i] . It extends the sign. You should change (short)bytes[i] to (bytes[i] & 0xff) . This will give you the correct answer.

It has nothing to do with byte overflow, contrary to most of the other answers. You don't have to change the array type either.

byte according to Java Docs :

The value of a byte is ranged between 2^(-7) and (2^7)-1 (-128 to 127).

But your value 0xEF (in decimal 239) has already reached the limit of a byte. That's what cause the sum give the wrong numbers.

As mentioned above by aprian, while byte has the necessary 8 bits for your hex values, it can only store values between -128 and 127. So a quick and easy solution would be to use the next bigger primitive, in this case short .

short shorts[] = {0xEF, 0x01, 0xEF, 0x01, 0x33, 0x0C, 0xB8, 0xE5, 0xFC, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

int checkSum = 0;

for( short s : shorts){
    checkSum = checkSum + s;
}

System.out.println("Checksum: " + Integer.toHexString(checkSum));

That gives me the output:

Checksum: ce4

Of course this means you might have to convert your byte array beforehand.

finally i got...

corrected code

void CalculateCheckSum( byte[] bytes ){
         short CheckSum = 0, i = 0;
         for( i = 0; i < bytes.length; i++){
              CheckSum += (short)(bytes[i] & 0xFF);
         }
         Log.i("Checksum", Integer.toHexString(CheckSum));
    }

thanks to aprian and others

You should use integers as input if you convert them with:

    String CalculateCheckSum( Integer[] bytes ){
        Integer CheckSum = 0, i = 0;
        for( i = 0; i < bytes.length; i++ ){
            CheckSum += bytes[i];
        }
        return Integer.toHexString(CheckSum);
    }

this will return the expected 0xCE4 hope this fixed your problem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM