Чи можу я на Java визначити цілочисельну константу у двійковому форматі?


85

Подібно до того, як ви можете визначити цілу константу в шістнадцятковій чи вісімковій, чи можу я це зробити в двійковій формі?

Я визнаю, що це справді легке (і дурне) питання. Мої пошукові запити в Google з’являються порожніми.


2
Просто FYI, майже в усіх мовах програмування ідіома полягає в тому, щоб писати двійкові константи в шістнадцятковій формі, а не власне двійковій рядку.
abyx

3
Правильно, але я гадаю, що це тому, що hex - це найближче, що є в наявності, а не тому, що з бінарним файлом щось не так. У мовах, якими я користувався, які підтримують двійкові літерали, я не думаю, що домовленість полягає в ігноруванні цієї функції.
Кен


2017 рік: прийнятою відповіддю має бути відповідь, надана Руссом. Див .: stackoverflow.com/a/1692932/716079
Лоуренко

Відповіді:


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
Для тих, хто цікавиться тим самим, що і Майк, це тому, що компілятор перетворює його в число, яке він представляє - у вас може бути десятки початкових нулів, і вони не вплинуть на фактичне значення. Процес компіляції по суті такий самий, як якщо б ви написали там десятковий знак.
Luke Briggs

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

@Russ Що тут означає 0b? Як ця функція називається в Java 7?
Geek

1
0b означає двійковий. Функція називається двійковими літералами: docs.oracle.com/javase/7/docs/technotes/guides/language/…
Русс Хейворд

1
Полюбіть це нове представлення двійкових даних. Представлення рядка було б дуже важко прочитати. Подивіться на різницю прийнятої відповіді та відповіді від "@ user12345613". +1 для нього.
Марчелло де Продаж

54

У Java немає бінарних літералів, але я припускаю, що ви могли б це зробити (хоча я не бачу сенсу):

int a = Integer.parseInt("10101010", 2);

1
Серед інших застосувань, шаблон строкання для растеризації ліній та багатокутників визначається цілим числом у декількох популярних графічних бібліотеках. Використання parseInt або parseShort дозволяє розробнику легко візуалізувати шаблон.
charstar

5
Починаючи з Java 7, відповідь Русса Хейворда є правильною. До Java 7 ви можете використовувати онлайн-інструмент або ваш улюблений калькулятор, щоб перетворити двійковий файл в одне із позначень, визнаних старими версіями Java (вісімкове, десяткове або шістнадцяткове). Якщо використовується інший radix, в декларації може бути розміщений описовий коментар, що містить двійкове представлення, щоб уточнити значення для читачів.
Jason C,

Це досить брудне рішення, чи не так? Ви просто берете 16 байт, щоб представити 1 байт (не враховуючи другий аргумент і перетворення). Звичайно, якщо компілятор не оптимізує це, що я сумніваюся.
Томаш Зато - відновити Моніку

@ TomášZato: Так, це так, але яке рішення ви б запропонували, враховуючи, що мова не підтримувала бінарні літерали, коли я писав цю відповідь? Рус Хейворд повинен прийняти прийняту відповідь зараз.
Ed S.

Я б запропонував відмовитися від комфорту та використовувати цілі числа. У самому визначенні змінної це нормально, але ця відповідь може спонукати користувачів використовувати цей підхід для циклів тощо. І загалом, я думаю, програміст повинен спробувати поступитися власним комфортом для певної продуктивності.
Томаш Зато - відновити Моніку

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 під час розробки.


Блискуче рішення! (публічна остаточна статична довга маска12 = 1L << 12;)
Jyro117

16

Використання двійкових констант для маскування

Оголосіть константи:

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
}

12

Шукайте в Google "синтаксис літералів Java", і ви придумаєте кілька записів.

Існує вісімковий синтаксис (префікс вашого числа 0), десятковий синтаксис та шістнадцятковий синтаксис із префіксом "0x". Але відсутність синтаксису двійкових записів.

Кілька прикладів:

int i = 0xcafe ; // hexadecimal case
int j = 045 ;    // octal case
int l = 42 ;     // decimal case

1
Це не відповідає на запитання.
Michael McQuade

2017 рік: На щастя, існує позначення двійкового подання. Починається з "0b". Приклад: byte b = 0b01000001(для кращої готовності byte b = 0b0100_0001).
Lourenco

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"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.