Могу ли я определить целочисленную константу в двоичном формате в Java?

85

Подобно тому, как вы можете определить целочисленную константу в шестнадцатеричном или восьмеричном формате, могу ли я сделать это в двоичном формате?

Признаюсь, это действительно простой (и глупый) вопрос. Мои поиски в Google заканчиваются пустыми.

Аарон Фай
источник
2
К вашему сведению, практически на каждом языке программирования идиома состоит в том, чтобы писать двоичные константы в шестнадцатеричном формате, а не фактическую двоичную строку.
abyx
3
Верно, но я полагаю, что это потому, что шестнадцатеричный - самый близкий из доступных, а не потому, что с двоичным что-то не так. Я не думаю, что в языках, которые я использовал, которые действительно поддерживают двоичные литералы, игнорируется эта функция.
Ken
2017 год: принятый ответ должен быть предоставлен Расс. См: stackoverflow.com/a/1692932/716079
Lourenco

Ответы:

65

Итак, с выпуском Java SE 7 двоичная нотация становится стандартной из коробки. Синтаксис довольно прост и очевиден, если вы хорошо разбираетесь в двоичном коде:

byte fourTimesThree = 0b1100;
byte data = 0b0000110011;
short number = 0b111111111111111; 
int overflow = 0b10101010101010101010101010101011;
long bow = 0b101010101010101010101010101010111L;

И, в частности, в том, что касается объявления переменных уровня класса как двоичных файлов, нет абсолютно никаких проблем с инициализацией статической переменной с использованием двоичной записи:

public static final int thingy = 0b0101;

Только будьте осторожны, не переполняйте числа слишком большим количеством данных, иначе вы получите ошибку компилятора:

byte data = 0b1100110011; // Type mismatch: cannot convert from int to byte

Теперь, если вы действительно хотите проявить фантазию, вы можете комбинировать эту другую интересную новую функцию в Java 7, известную как числовые литералы с подчеркиванием. Взгляните на эти модные примеры двоичной записи с буквальным подчеркиванием:

int overflow = 0b1010_1010_1010_1010_1010_1010_1010_1011;
long bow = 0b1__01010101__01010101__01010101__01010111L;

Разве это не красиво и чисто, не говоря уже о удобочитаемости?

Я взял эти фрагменты кода из небольшой статьи, которую написал на эту тему на TheServerSide. Не стесняйтесь проверить это для получения более подробной информации:

Java 7 и двоичная нотация: овладение экзаменом на OCP Java Programmer (OCPJP)

Кэмерон Маккензи
источник
3
Почему ваши байтовые данные = 0b0000110011; имеет 10 бит? Я новичок в программировании, но думаю, что он должен выглядеть как 0b00110011, чтобы соответствовать 8 битам байтового типа данных.
Майк
1
Для всех, кто интересуется тем же, что и Майк, это потому, что компилятор преобразует его в число, которое он представляет - у вас могут быть десятки ведущих нулей, и они не повлияют на фактическое значение. Процесс компиляции по сути такой же, как если бы вы записали здесь десятичную дробь.
Люк Бриггс
1
по определению байт примитивного типа может хранить 256 чисел от -128 до 127 (от -128 до -1 и от 0 до 127). Но как представить -128 с помощью двоичного литерала. например, для байта b = -0b1111111; обозначает -127, а как насчет -128?
nirmalsingh
152

В Java 7:

int i = 0b10101010;

В более старых версиях Java нет двоичных литералов (альтернативы см. В других ответах).

Расс Хейворд
источник
33
Я также хотел бы отметить, что могут быть _символы, чтобы сделать последовательность более читаемой: int i = 0b1010_1010_0011;
user12345613 08
@Russ Что здесь означает 0b? Как эта функция называется в Java 7?
Geek
1
0b означает двоичный. Эта функция называется двоичными литералами: docs.oracle.com/javase/7/docs/technotes/guides/language/…
Расс Хейворд,
1
Мне нравится это новое представление двоичных данных. Представление String было бы очень трудно читать. Посмотрите, чем отличается принятый ответ от ответа «@ user12345613». +1 для него.
Марчелло де Сейлз,
54

В Java нет двоичных литералов, но я полагаю, что вы могли бы это сделать (хотя я не вижу в этом смысла):

int a = Integer.parseInt("10101010", 2);
Эд С.
источник
1
Помимо прочего, в нескольких популярных графических библиотеках узор пунктирной линии для растрирования линий и многоугольников указывается как целое число. Использование parseInt или parseShort позволяет разработчику легко визуализировать шаблон.
charstar
5
Начиная с Java 7, ответ Расса Хейворда является правильным. До Java 7 вы можете использовать онлайн-инструмент или свой любимый калькулятор для преобразования двоичного кода в одну из нотаций, распознаваемых старыми версиями Java (восьмеричную, десятичную или шестнадцатеричную). Если используется другая система счисления, описательный комментарий, содержащий двоичное представление, может быть помещен в объявление, чтобы прояснить значение для читателей.
Jason C
Это довольно грязное решение, не правда ли? Вы просто берете 16 байтов для представления 1 байта (не считая второго аргумента и преобразования). Конечно, если компилятор не оптимизирует это, в чем я сомневаюсь.
Tomáš Zato - Reinstate Monica
@ TomášZato: Да, но какое решение вы бы предложили, учитывая, что язык не поддерживал двоичные литералы, когда я писал этот ответ? Теперь Расс Хейворд должен получить принятый ответ.
Эд С.
Я бы посоветовал отказаться от комфорта и использовать целые числа. В самом определении переменной это нормально, но этот ответ может побудить пользователей использовать этот подход для циклов и т. Д. И вообще, я думаю, что программист должен попытаться отказаться от собственного комфорта ради некоторой производительности.
Tomáš Zato - Reinstate Monica
18

Ответ от Эда Свангрена

public final static long mask12 = 
  Long.parseLong("00000000000000000000100000000000", 2);

работает отлично. Я использовал longвместо intи добавил модификаторы, чтобы прояснить возможное использование в качестве битовой маски. Однако у такого подхода есть два неудобства.

  1. Прямой ввод всех этих нулей подвержен ошибкам
  2. Результат недоступен в десятичном или шестнадцатеричном формате на момент разработки.

Могу предложить альтернативный подход

public final static long mask12 = 1L << 12;

Это выражение делает очевидным, что 12-й бит равен 1 (счет начинается с 0, справа налево); и когда вы наводите курсор мыши, всплывающая подсказка

long YourClassName.mask12 = 4096 [0x1000]

появляется в Eclipse. Вы можете определить более сложные константы, например:

public final static long maskForSomething = mask12 | mask3 | mask0;

или явно

public final static long maskForSomething = (1L<<12)|(1L<<3)|(1L<<0);

Значение переменной maskForSomethingбудет по-прежнему доступно в Eclipse во время разработки.

чгман
источник
Гениальное решение! (public final static long mask12 = 1L << 12;)
Jyro117
17

Использование двоичных констант для маскировки

Объявить константы:

public static final int FLAG_A = 1 << 0;
public static final int FLAG_B = 1 << 1;
public static final int FLAG_C = 1 << 2;
public static final int FLAG_D = 1 << 3;

и использовать их

if( (value & ( FLAG_B | FLAG_D )) != 0){
    // value has set FLAG_B and FLAG_D
}
pawelzieba
источник
12

Поищите в Google "синтаксис литералов Java", и вы найдете несколько записей.

Существует восьмеричный синтаксис (префикс номера с 0), десятичный синтаксис и шестнадцатеричный синтаксис с префиксом "0x". Но нет синтаксиса для двоичной записи.

Некоторые примеры:

int i = 0xcafe ; // hexadecimal case
int j = 045 ;    // octal case
int l = 42 ;     // decimal case
Пьер
источник
1
Это не отвечает на вопрос.
Майкл Маккуэйд
Год 2017: К счастью, есть обозначения для двоичного представления. Начинается с «0b». Пример: byte b = 0b01000001(для удобства чтения byte b = 0b0100_0001).
Лоуренсу
2

Если вы хотите возиться с большим количеством двоичных файлов, вы можете определить некоторые константы:

public static final int BIT_0 = 0x00000001;
public static final int BIT_1 = 0x00000002;

и т.п.

или

public static final int B_00000001 = 0x00000001;
public static final int B_00000010 = 0x00000002;
public static final int B_00000100 = 0x00000004;
Энтони Хейворд
источник
0

Чуть более неудобный ответ:

public class Main {

    public static void main(String[] args) {
        byte b = Byte.parseByte("10", 2);
        Byte bb = new Byte(b);
        System.out.println("bb should be 2, value is \"" + bb.intValue() + "\"" );
    }

}

который выводит [java] bb должен быть 2, значение - "2"

NSherwin
источник