简体   繁体   中英

16 bit Rotate Left and Right for Java

I have tried to search for circular rotate left and circular rotate right for 16 bits of data (not the 8 bit ones) in Java but most circular rotates I can find handles 8 bits of data. How do I perform 16 bits of circular rotate left and right in Java ? Thanks.

Below are my current codes that do not work:

public byte[] rotr(byte[] input, int shift) {
    int output = (binToInt(input) << shift) | (binToInt(input) >> (16 - shift));
    return BigInteger.valueOf(output).toByteArray();
}

public int binToInt(byte[] b) {
    return new BigInteger(b).intValue();
}

public String byteToHex(byte b) {
    char hexDigit[] = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };
    char[] array = {hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f]};
    return new String(array);
}

public String byteArrayToHex(byte[] bytes) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        sb.append(byteToHex((byte) bytes[i]));
    }
    return sb.toString();
}

public static void main(String[] args) {
    byte[] out = rotr(new byte[] {(byte) 0x97, (byte) 0xA1}, 7);
    System.out.println(byteArrayToHex(out));
}

Hex (0x97A1) bit string: 1001011110100001

After attempted rotr-7: 11001011;

Excepted bit string: 1101000011001011 (0xD0CB)

You are really making things hard on yourself by putting data into a byte array. This makes it also hard to tell if your problem is in the conversion or in the rotation.

The rotation itself pretty simple:

 public static int ror16(int data, int distance) {
     distance &= 15; // limit rotation to distance mod 16
     data &= 0xFFFF; // ensure only the lower 16 bits can be set
     return (data >> distance) | (data << (16 - distance));
 }

Note that when shifting an int (supposedly holding 16 bits) to the right you need to ensure that the upper 16 bits are really zeros, otherwise you will be shifting in garbage.

Your problems most likely stem from the conversion from byte[] to int. The constructor BigInteger(byte[]) will assume that the value is signed , thus your BigInteger when converted to int gives you 0xFFFF97A1. That trips up your rotation, since you do not account for the upper bits being set.

Edit: Drop all the byte[] fluff and just use the more sensible int for handling 16 bit values:

public static main(String[] argv) {
    int result = ror16(0x97A1, 7) & 0xFFFF;
    System.out.println(Integer.toHexString(result));
}

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