如何确定是否在十六进制字符串中设置了一位?
How to determine if a bit is set in a hex-decimal string?
我有一个十六进制格式的字符串,例如:
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));
我得到一个 'false' 结果:
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
我做错了什么?
如何正确判断十六进制字符串中是否设置了某个位?
对于大的十六进制数,一个简单的方法如下:
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
我希望所有这些不同类型的解决方案可以帮助您解决问题。
我很快就解决了这个问题:这个解决方案不会先将整个字符串转换为数字,而是在检查位之前尝试挑选出正确的字符:
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
在此实现中,bitnr
必须至少为 1。基本上是单索引的。我添加了一些错误处理以确保 bitnr
保持在十六进制范围内。
它找到有问题的确切 1 长度 substring
,并使用 bitwise OR
来确定是否设置了特定位:
public class WhosebugTest {
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;
}
}
感谢您的回答。
我想根据您的建议提供我的解决方案(不是最优的,但可以 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
我有一个十六进制格式的字符串,例如:
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));
我得到一个 'false' 结果:
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
我做错了什么?
如何正确判断十六进制字符串中是否设置了某个位?
对于大的十六进制数,一个简单的方法如下:
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
我希望所有这些不同类型的解决方案可以帮助您解决问题。
我很快就解决了这个问题:这个解决方案不会先将整个字符串转换为数字,而是在检查位之前尝试挑选出正确的字符:
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
在此实现中,bitnr
必须至少为 1。基本上是单索引的。我添加了一些错误处理以确保 bitnr
保持在十六进制范围内。
它找到有问题的确切 1 长度 substring
,并使用 bitwise OR
来确定是否设置了特定位:
public class WhosebugTest {
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;
}
}
感谢您的回答。
我想根据您的建议提供我的解决方案(不是最优的,但可以 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