如何确定是否在十六进制字符串中设置了位?

问题描述 投票:4回答:4

我有一个十六进制格式的字符串,例如:

AAE04471

我认为,在二进制视图中,该字符串必须类似于:

10101010 11100000 01000100 01110001

我正在尝试确定是否像这样设置了32位:

 String s = "AAE04471";
 byte[] bytes = DatatypeConverter.parseHexBinary(s);
 System.out.println("Length bytes[] = " + bytes.length);
 BitSet bitset = BitSet.valueOf(bytes);
 System.out.println("Length of bitset = " + bitset.length());
 System.out.println("Look of bitset = " + bitset.toString());
 System.out.println("32 bit is " + bitset.get(31));

我得到“假”结果:

Length bytes[] = 4
Length of bitset = 31
Look of bitset = {1, 3, 5, 7, 13, 14, 15, 18, 22, 24, 28, 29, 30}
32 bit is false

结果是完全不同且奇怪的位顺序!

01010101 00000111 00100010 1000111

我在做什么错?

如何正确确定是否在十六进制字符串中设置了位?

java bitset
4个回答
2
投票

我很快就将它们一起砍掉了:此解决方案不会首先将整个字符串转换为数字,而是会在检查该位之前尝试挑选出正确的字符:

public class Test {

    public static void main(String[] args) {
        for (int i = 0; i < 16; i++) {
            test("DEAD", i);
        }
    }

    public static boolean isBitSet(String hex, int bit) {
        int n = bit >> 2;
        int last = hex.length() - 1;
        if (n < 0 || n > last) return false;
        char c = hex.charAt(last - n);
        int v = Integer.parseInt(Character.toString(c), 16);
        int mask = 1 << (bit & 3);
        return (v & mask) != 0;
    }

    public static void test(String hex, int bit) {
        boolean set = isBitSet(hex, bit);
        System.out.format("%s, bit %2d, %s%n", hex, bit, set ? "set" : "not set");
    }

}

输出:

DEAD, bit  0, set
DEAD, bit  1, not set
DEAD, bit  2, set
DEAD, bit  3, set
DEAD, bit  4, not set
DEAD, bit  5, set
DEAD, bit  6, not set
DEAD, bit  7, set
DEAD, bit  8, not set
DEAD, bit  9, set
DEAD, bit 10, set
DEAD, bit 11, set
DEAD, bit 12, set
DEAD, bit 13, not set
DEAD, bit 14, set
DEAD, bit 15, set

1
投票

在此实现中,bitnr必须至少为1。基本上是一个索引。我添加了一些错误处理,以确保bitnr保持在十六进制的范围内。

它找到所讨论的确切1长度substring,并使用bitwise OR标识是否设置了特定位:

public class StackOverflowTest {
  public static void main(String[] args) {
    System.out.println(bitSet("AAE04471",1));          // true
    System.out.println(bitSet("AAE04471",17));         // false
    System.out.println(bitSet("AAE04471",32));         // true
    System.out.println(bitSet("AAE04471AAE04471",32)); // true
    System.out.println(bitSet("AAE04471AAE04471",40)); // false
    System.out.println(bitSet("AAE04471AAE04471",64)); // true
//    System.out.println(bitSet("AAE04471AAE04471",0));  // AssertionError
//    System.out.println(bitSet("AAE04471AAE04471",65)); // AssertionError
  }

  private static boolean bitSet(String hexString, int bitnr) {
    if (bitnr < 1 || hexString.length() * 4 < bitnr) {
      throw new AssertionError("bitnr is out of bounds");
    }

    // add 3 to the bitnr to make division by 4 go to correct index
    String bitString = hexString.substring(hexString.length()-(bitnr+3)/4,
                                           hexString.length()-(bitnr+3)/4+1);
    int check = Integer.parseInt(bitString,16);
    int OrInt = 1 << (bitnr + 3) % 4; // add 3 to the bitnr to make % 4 go to 3 for highest.
    return (check & OrInt) == OrInt;
  }
}

1
投票

对于大十六进制的简单方法如下:

import java.math.BigInteger;

public class Main {
    public static void main(String[] args) {
        String hex = "AAE04471";
        System.out.println("Hexadecimal string: " + hex);

        BigInteger bigInt = new BigInteger(hex, 16);

        String binary = bigInt.toString(2);
        System.out.println("Binary string: " + binary);

        System.out.println("\nBit information:");
        System.out.println("32nd bit is " + (binary.charAt(binary.length() - 32) == '1' ? true : false));
        System.out.println("31st bit is " + (binary.charAt(binary.length() - 31) == '1' ? true : false));
        System.out.println("30th bit is " + (binary.charAt(binary.length() - 30) == '1' ? true : false));

        // Alternatively,
        System.out.println("\nBit information using an alternative method:");
        System.out.println("32nd bit is " + bigInt.testBit(31));
        System.out.println("31st bit is " + bigInt.testBit(30));
        System.out.println("30th bit is " + bigInt.testBit(29));
    }
}

输出:

Hexadecimal string: AAE04471
Binary string: 10101010111000000100010001110001

Bit information:
32nd bit is true
31st bit is false
30th bit is true

Bit information using an alternative method:
32nd bit is true
31st bit is false
30th bit is true

[更新]

现在,我已经设计出一种适用于任何长度的十六进制数的方法。下面给出的是解决方案以及一些测试:

public class Main {
    public static void main(String[] args) {
        String hex = "AAE04471";
        String binary = hexadecimalToBinary(hex);
        System.out.println("Hexadecimal: " + hex);
        System.out.println("Binary: " + binary);
        System.out.println("Is bit number 32 set: " + isBitSet(binary, 32));
        System.out.println("Is bit number 31 set: " + isBitSet(binary, 31));
        System.out.println("Is bit number 30 set: " + isBitSet(binary, 30));
        System.out.println("---------------------------------------------");        
        hex = "AAE044710C0000000000000000FF0000";
        binary = hexadecimalToBinary(hex);
        System.out.println("Hexadecimal: " + hex);
        System.out.println("Binary: " + binary);
        System.out.println("Is bit number 32 set: " + isBitSet(binary, 32));
        System.out.println("Is bit number 31 set: " + isBitSet(binary, 31));
        System.out.println("Is bit number 30 set: " + isBitSet(binary, 30));
    }

    static String hexadecimalToBinary(String hexadecimal) {
        String binary = hexadecimal;
        String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
        String[] hextoBinaryDigits = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001",
                "1010", "1011", "1100", "1101", "1110", "1111" };
        for (int i = 0; i < hexDigits.length; i++)
            binary = binary.replaceAll(hexDigits[i], hextoBinaryDigits[i]);
        return binary;
    }

    static boolean isBitSet(String binary, int bitNumber) {
        if (bitNumber > binary.length()) {
            return false;
        }
        return binary.charAt(binary.length() - bitNumber) == '1' ? true : false;
    }
}

输出:

Hexadecimal: AAE04471
Binary: 10101010111000000100010001110001
Is bit number 32 set: true
Is bit number 31 set: false
Is bit number 30 set: true
---------------------------------------------
Hexadecimal: AAE044710C0000000000000000FF0000
Binary: 10101010111000000100010001110001000011000000000000000000000000000000000000000000000000000000000000000000111111110000000000000000
Is bit number 32 set: false
Is bit number 31 set: false
Is bit number 30 set: false

[[第二次更新]

最后,我设计了一种方法,该方法适用于任意长度的十六进制数,也可以将整个十六进制数都不转换为二进制数。而是,此方法仅将一个十六进制数字(十六进制数字位于要查找其状态的位数)转换为二进制字符串。下面给出的是解决方案以及一些测试:

public class Main {
    public static void main(String[] args) {
        String hex = "AAE04471";
        System.out.println("Hexadecimal: " + hex);
        System.out.println("Is bit number 32 set: " + isBitSet(hex, 32));
        System.out.println("Is bit number 31 set: " + isBitSet(hex, 31));
        System.out.println("Is bit number 30 set: " + isBitSet(hex, 30));
        System.out.println("----------------------");
        hex = "AAE044710C0000000000000000FF0000";
        System.out.println("Hexadecimal: " + hex);
        System.out.println("Is bit number 32 set: " + isBitSet(hex, 32));
        System.out.println("Is bit number 31 set: " + isBitSet(hex, 31));
        System.out.println("Is bit number 30 set: " + isBitSet(hex, 30));
    }

    static boolean isBitSet(String hex, int bitNumber) {
        if (bitNumber > hex.length() * 4) {
            return false;
        }
        int i = bitNumber % 4 == 0 ? bitNumber / 4 : bitNumber / 4 + 1;

        // Get the hexadecimal digit where lies the bit number whose status is to be
        // found.
        StringBuilder sb = new StringBuilder().append(hex.charAt(hex.length() - i));

        // Get the decimal equivalent of the hexadecimal digit
        int n = Integer.parseInt(sb.toString(), 16);

        // Convert the binary equivalent of the hexadecimal digit into 4-digit string by
        // left-padding 0
        String binaryStringIn4Digits = String.format("%1$" + 4 + "s", Integer.toBinaryString(n)).replace(' ', '0');

        return binaryStringIn4Digits.charAt(3 - bitNumber % 4) == '1' ? true : false;
    }
}

输出:

Hexadecimal: AAE04471
Is bit number 32 set: false
Is bit number 31 set: true
Is bit number 30 set: false
----------------------
Hexadecimal: AAE044710C0000000000000000FF0000
Is bit number 32 set: false
Is bit number 31 set: false
Is bit number 30 set: false

我希望所有这些不同类型的解决方案都能帮助您解决问题。


0
投票

感谢您的回答。

我想根据您的建议提供解决方案(不是最佳解决方案,但可以100%起作用:]

 private static boolean bitSet(String hexString, int bitPos)  {
        if (bitPos < 1) {
            throw new IllegalArgumentException("Bit position '" + bitPos + "' must be > 0");
        }
        if (hexString == null || hexString.trim().length() == 0 || hexString.trim().length() % 2 != 0) {
            throw new IllegalArgumentException("HEX string '" + hexString + "' is bad");
        }
        hexString = hexString.trim();

        StringBuilder bitString = new StringBuilder();

        for (int i = 0; i < hexString.length(); i += 2) {
            String byteStr = hexString.substring(i, i + 2);
        //    System.out.println("HEX byte '" +  byteStr + "'");
            String binary = new BigInteger(byteStr, 16).toString(2);
        //     System.out.println("binary '" +  binary + "'");
            if(binary.length() < 8 ) {
                binary = "00000000".substring(0, 8 - binary.length()) + binary;
            }
            bitString.append(binary);
        }

        System.out.println(bitString);

        if (bitString.length() < bitPos) {
            System.out.println(bitPos + "-nd bit is not contain in HEX  '" + hexString + "'");
            return false;
        }

        System.out.println(bitPos + "-nd bit is " + (bitString.charAt(bitPos - 1) == '1'));
        return bitString.charAt(bitPos - 1) == '1';
    }

测试:

    bitSet("0101", 8);
    bitSet("AAE04471", 32);
    bitSet("AAE044710C0000000000000000000000", 32);
    bitSet("AAE044710C000000000000000000000", 32);

输出:

0000000100000001
8-nd bit is true
10101010111000000100010001110001
32-nd bit is true
10101010111000000100010001110001000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
32-nd bit is true
Exception in thread "main" java.lang.IllegalArgumentException: HEX string 'AAE044710C000000000000000000000' is bad
© www.soinside.com 2019 - 2024. All rights reserved.