Обновление: Отображение формата битов без знака, добавленные версии long
и BigInteger
и добавленные версии без знака.
Класс Integer
имеет много static
методов для создания бит магии.Не нужно использовать BigInteger
, если ввод int
.Long
имеет те же методы, если это необходимо.
Вот метод для проведения требуемого теста.Он использует:
bitCount(int i)
- Возвращает число однобитных в двоичном представлении дополнения двух указанного int
значение.
numberOfLeadingZeros(int i)
- Возвращает число нулевых битов, предшествующих однобитному старшему («крайнему левому») разряду inдвоичное представление дополнения до двух указанных значений int
.Возвращает 32, если указанное значение не имеет однобитовых значений в представлении дополнения до двух, другими словами, если оно равно нулю.
SIZE
-число битов, используемых для представления значения типа int в двоичной форме дополнения до двух (мы все знаем, что это 32) .
Поскольку мы хотим игнорировать ведущие нули, SIZE - numberOfLeadingZeros
сообщит нам фактическое количество использованных битов.
public static boolean oneBitsEqualsZeroBits(int value) {
if (value == 0)
return false;
int bitsUsed = Integer.SIZE - Integer.numberOfLeadingZeros(value);
int oneBits = Integer.bitCount(value);
int zeroBits = bitsUsed - oneBits;
return (oneBits == zeroBits);
}
Оно может быть сокращено, хотя и немного неясно, но объяснимо.Предположим, 0s == 1s, поэтому bitCount
- это число 1s + bitCount
- это число 0s, т.е. bitCount * 2
- это количество используемых битов.Добавьте число лидирующих нулей и все биты int
должны быть учтены.
public static boolean oneBitsEqualsZeroBits(int value) {
return (value != 0 && Integer.numberOfLeadingZeros(value) + 2 * Integer.bitCount(value) == 32);
}
То же самое для long
версии:
public static boolean oneBitsEqualsZeroBits(long value) {
return (value != 0 && Long.numberOfLeadingZeros(value) + 2 * Long.bitCount(value) == 64);
}
Для BigInteger
, считая старшиенули не имеют смысла, так как без фиксированной битовой ширины нет ведущих нулей.Вместо этого у нас есть другой метод:
bitLength()
: Возвращает количество бит в минимальном представлении с двумя дополнительными символами этого BigInteger
, исключая знаковый бит.
Поскольку бит знака исключен, мы должны добавить его обратно, чтобы соответствовать версиям int
и long
.
public static boolean oneBitsEqualsZeroBits(BigInteger value) {
if (value.signum() == 0)
return false;
if (value.signum() > 0)
return (2 * value.bitCount() == value.bitLength());
return (2 * value.bitCount() == value.bitLength() + 1);
}
3 версиибудет обрабатывать отрицательные значения по-разному, поскольку int
и long
будут выполнять расширение знака до 32 и 64 бит соответственно.
Тест (только для версии int
)
public static void main(String[] args) {
test(0, false);
test(1, false);
test(0b10, true);
test(0b11, false);
test(0b100, false);
test(0b1000, false);
test(0b1001, true);
test(0b1010, true);
test(0b1011, false);
test(0b1100, true);
test(0b1101, false);
test(0b101010_11110000_00111100_00001111, true);
test(0b11001100_01010101_01100110_11100010, true);
test(0b11111111_11111111_11111111_11111111, false);
}
public static void test(int value, boolean expected) {
boolean result = oneBitsEqualsZeroBits(value);
System.out.printf("%11d %8x %-5s %3s %s%n", value, value, result,
(result == expected ? "OK" : "ERR"),
Integer.toUnsignedString(value, 2));
}
Вывод (заголовок добавлен вручную для ответа)
Decimal Hex Result Binary
0 0 false OK 0
1 1 false OK 1
2 2 true OK 10
3 3 false OK 11
4 4 false OK 100
8 8 false OK 1000
9 9 true OK 1001
10 a true OK 1010
11 b false OK 1011
12 c true OK 1100
13 d false OK 1101
720387087 2af03c0f true OK 101010111100000011110000001111
-866818334 cc5566e2 true OK 11001100010101010110011011100010
-1 ffffffff false OK 11111111111111111111111111111111
Игнорирующий знак
Если вы хотите сравнить 1си 0 на строковом представлении числа, игнорируя знак, т.е. на abs(value)
, затем вы меняете методы для применения abs()
:
public static boolean oneBitsEqualsZeroBits(int value) {
if (value == 0 || value == Integer.MIN_VALUE)
return false;
if (value < 0)
value = -value;
return (Integer.numberOfLeadingZeros(value) + 2 * Integer.bitCount(value) == 32);
}
public static boolean oneBitsEqualsZeroBits(long value) {
if (value == 0 || value == Long.MIN_VALUE)
return false;
if (value < 0)
value = -value;
return (Long.numberOfLeadingZeros(value) + 2 * Long.bitCount(value) == 64);
}
public static boolean oneBitsEqualsZeroBits(BigInteger value) {
value = value.abs();
return (value.signum() != 0 && 2 * value.bitCount() == value.bitLength());
}