monoceres
monoceres

Reputation: 4770

Signed/unsigned situation when converting c# to java

I'm currently converting the following piece of code to java from c#:

    public static byte MakeCS(byte[] arr)
    {
        byte cs = 0;
        for (int i = 0; i < arr.Length; i++)
        {
            cs += arr[i];
        }
        return cs;
    }

My naive conversation is to just change the arr.Length to arr.length ;)

However this gives me incorrect checksums since java has signed bytes and c# has unsigned ones (I tried changing the c# code to sbyte and it worked fine).

What is the correct way to handkle the situation? I know I can "convert" a java byte to unsigned by bitand'ing it with 0xFF, but I'm not sure where to do this!

Thanks!

Upvotes: 2

Views: 632

Answers (3)

Peter Lawrey
Peter Lawrey

Reputation: 533720

You only need to change the return value and make the return type int

return cs & 0xFF;

You don't need to change the type of cs as it will give the same result whether its an int, short or long after using 0xFF. You don't need to mask each value either.

public static void main(String... args) {
    byte[] bytes = { 1, -128, -1 }; // check sum is -128 or 0x80 or 128 (unsigned)
    System.out.println("makeCS "+ makeCS(bytes));
    System.out.println("makeCS2 "+ makeCS2(bytes));
    System.out.println("makeCS3 "+ makeCS3(bytes));
}

public static int makeCS(byte... arr) {
    byte cs = 0;
    for (byte b : arr)
        cs += b;
    return cs & 0xFF;
}

public static int makeCS2(byte[] arr)
{
    int cs = 0;
    for (int i = 0; i < arr.length; i++)
    {
        int add = arr[i];
        cs += (0xFF & add);
        cs &= 0xFF;
    }
    return cs;
}

public static short makeCS3(byte[] arr)
{
    short cs = 0;
    for (int i = 0; i < arr.length; i++)
    {
        cs += arr[i];
    }
    return cs;
}

prints

makeCS 128
makeCS2 128
makeCS3 -128

Upvotes: 2

JaredPar
JaredPar

Reputation: 755259

It sounds like you're expecting to use the entire 8 bits of the c# byte in order to do the sum. In order to correctly port to Java you'll need to pick a type which has at least the same precision. The closest type in Java is short.

public static short MakeCS(byte[] arr)
{
    short cs = 0;
    for (int i = 0; i < arr.length; i++)
    {
        cs += arr[i];
    }
    return cs;
}

Note: This isn't a perfect port though. It opens the possibility that code which would overflow in C# won't overflow in the Java version since Java short has more precision that C# byte.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726909

Try this:

public static byte MakeCS(byte[] arr)
{
    int cs = 0;
    for (int i = 0; i < arr.Length; i++)
    {
        int add = arr[i];
        cs += (0xFF & add);
        cs &= 0xFF;
    }
    return cs;
}

This will truncate the sign portion of the int before adding it to CS, and ten truncate everything past the eight's bit once again to emulate unsigned addition.

Upvotes: 1

Related Questions