Двоичные литералы?

скопировано из документа pytorch :

a = torch.ones(5)
print(a)

тензор ([1., 1., 1., 1., 1.])

blockquote>
b = a.numpy()
print(b)

[1. 1. 1. 1. 1.]

blockquote>

48
задан Joachim Sauer 5 September 2011 в 23:38
поделиться

13 ответов

Я использовал бы немного оператор сдвига:

const int has_nukes        = 1<<0;
const int has_bio_weapons  = 1<<1;
const int has_chem_weapons = 1<<2;
// ...
int dangerous_mask = has_nukes | has_bio_weapons | has_chem_weapons;
bool is_dangerous = (country->flags & dangerous_mask) == dangerous_mask;

Это еще лучше, чем лавинная рассылка 0.

61
ответ дан strager 7 November 2019 в 12:00
поделиться

Как в стороне:

Особенно, если Вы имеете дело с большим набором, вместо того, чтобы пройти [незначительное] умственное усилие по записи последовательности объемов сдвига, можно заставить каждую константу зависеть от ранее определенной константы:

const int has_nukes        = 1;
const int has_bio_weapons  = has_nukes        << 1;
const int has_chem_weapons = has_bio_weapons  << 1;
const int has_nunchuks     = has_chem_weapons << 1;
// ...

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

const int has_nukes        = 1;
const int has_gravity_gun  = has_nukes        << 1; // added
const int has_bio_weapons  = has_gravity_gun  << 1; // changed
const int has_chem_weapons = has_bio_weapons  << 1; // unaffected from here on
const int has_nunchuks     = has_chem_weapons << 1;
// ...

Выдерживают сравнение с:

const int has_nukes        = 1 << 0;
const int has_bio_weapons  = 1 << 1;
const int has_chem_weapons = 1 << 2;
const int has_nunchuks     = 1 << 3;
// ...
const int has_scimatar     = 1 << 28;
const int has_rapier       = 1 << 28; // good luck spotting this typo!
const int has_katana       = 1 << 30;

И:

const int has_nukes        = 1 << 0;
const int has_gravity_gun  = 1 << 1;  // added
const int has_bio_weapons  = 1 << 2;  // changed
const int has_chem_weapons = 1 << 3;  // changed
const int has_nunchuks     = 1 << 4;  // changed
// ...                                // changed all the way
const int has_scimatar     = 1 << 29; // changed *sigh*
const int has_rapier       = 1 << 30; // changed *sigh* 
const int has_katana       = 1 << 31; // changed *sigh*

Как в стороне к моему в стороне, вероятно, одинаково трудно определить опечатку как это:

const int has_nukes        = 1;
const int has_gravity_gun  = has_nukes        << 1;
const int has_bio_weapons  = has_gravity_gun  << 1;
const int has_chem_weapons = has_gravity_gun  << 1; // oops!
const int has_nunchuks     = has_chem_weapons << 1;

Так, я думаю, что основное преимущество этого каскадного синтаксиса при контакте со вставками и удалениями констант.

1
ответ дан Ates Goral 7 November 2019 в 12:00
поделиться

Нет никакого синтаксиса для литеральных двоичных констант в C++ пути, там для шестнадцатеричного и восьмеричного. Самая близкая вещь для того, что похоже, что Вы пытаетесь сделать, состояла бы в том, чтобы, вероятно, изучить и использовать bitset.

1
ответ дан Bill the Lizard 7 November 2019 в 12:00
поделиться

Java не поддерживает двоичные литералы также, к сожалению. Однако это имеет перечисления , который может использоваться с EnumSet . EnumSet представляет перечислимые значения внутренне с битовыми полями и представляет Set интерфейс для управления этими флагами.

, С другой стороны, Вы могли использовать разрядные смещения (в десятичном числе) при определении значений:

const int HAS_NUKES        = 0x1 << 0;
const int HAS_BIO_WEAPONS  = 0x1 << 1;
const int HAS_CHEM_WEAPONS = 0x1 << 2;
2
ответ дан Zach Scrivena 7 November 2019 в 12:00
поделиться

Я пишу двоичные литералы как это:

const int has_nukes        = 0x0001;
const int has_bio_weapons  = 0x0002;
const int has_chem_weapons = 0x0004;

Это более компактно, чем Ваша предложенная нотация и легче читать. Например:

const int upper_bit = 0b0001000000000000000;

по сравнению с:

const int upper_bit = 0x04000;

Вы заметили, что версия двоичных файлов не была даже несколькими 4 битами? Вы думали, что это был 0x10000?

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

4
ответ дан Darron 7 November 2019 в 12:00
поделиться

Термин, который Вы хотите, двоичные литералы

, Ruby имеет их с синтаксисом, который Вы даете.

Одна альтернатива должна определить макросы помощника для преобразования для Вас. Я нашел следующий код в http://bytes.com/groups/c/219656-literal-binary

/* Binary constant generator macro
 * By Tom Torfs - donated to the public domain
 */

/* All macro's evaluate to compile-time constants */

/* *** helper macros *** */

/* turn a numeric literal into a hex constant
 * (avoids problems with leading zeroes)
 * 8-bit constants max value 0x11111111, always fits in unsigned long
 */
#define HEX_(n) 0x##n##LU

/* 8-bit conversion function */
#define B8_(x) ((x & 0x0000000FLU) ?   1:0) \
             | ((x & 0x000000F0LU) ?   2:0) \
             | ((x & 0x00000F00LU) ?   4:0) \
             | ((x & 0x0000F000LU) ?   8:0) \
             | ((x & 0x000F0000LU) ?  16:0) \
             | ((x & 0x00F00000LU) ?  32:0) \
             | ((x & 0x0F000000LU) ?  64:0) \
             | ((x & 0xF0000000LU) ? 128:0)

/* *** user macros *** /

/* for upto 8-bit binary constants */
#define B8(d) ((unsigned char) B8_(HEX_(d)))

/* for upto 16-bit binary constants, MSB first */
#define B16(dmsb, dlsb) (((unsigned short) B8(dmsb) << 8) \
                                         | B8(dlsb))

/* for upto 32-bit binary constants, MSB first */
#define B32(dmsb, db2, db3, dlsb) (((unsigned long) B8(dmsb) << 24) \
                                 | ((unsigned long) B8( db2) << 16) \
                                 | ((unsigned long) B8( db3) <<  8) \
                                 |                  B8(dlsb))

/* Sample usage:
 * B8(01010101) = 85
 * B16(10101010,01010101) = 43605
 * B32(10000000,11111111,10101010,01010101) = 2164238933
 */
9
ответ дан pmttavara 7 November 2019 в 12:00
поделиться

<забастовка> Это обсуждение может быть интересна ... Возможно, был, поскольку ссылка является битой, к сожалению. Это описало основанный на шаблоне подход, подобный другим ответам здесь.

И также существует вещь, названная BOOST_BINARY.

9
ответ дан Anonymous 7 November 2019 в 12:00
поделиться

GCC поддерживает двоичные константы как расширение с тех пор 4.3. Посмотрите объявление (посмотрите на раздел "New Languages and Language specific improvements").

12
ответ дан bluebrother 7 November 2019 в 12:00
поделиться

Можно использовать < < если Вам нравится.

int hasNukes = 1;
int hasBioWeapons = 1 << 1;
int hasChemWeapons = 1 << 2;
13
ответ дан Jon B 7 November 2019 в 12:00
поделиться

Библиотека Стандарта C++ является Вашим другом:

#include <bitset>

const std::bitset <32> has_nukes( "00000000000000000000000000000001" );
16
ответ дан 7 November 2019 в 12:00
поделиться

Между прочим, следующая версия C++ будет поддерживать определяемые пользователем литералы. Они уже включены в рабочий проект. Это позволяет такой материал (давайте надеяться, что у меня нет слишком многих ошибок в нем):

template<char... digits>
constexpr int operator "" _b() {
    return conv2bin<digits...>::value;
}

int main() {
    int const v = 110110110_b;
}

conv2bin был бы шаблон как это:

template<char... digits>
struct conv2bin;

template<char high, char... digits>
struct conv2bin<high, digits...> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0') * (1 << sizeof...(digits)) + 
                             conv2bin<digits...>::value;
};

template<char high>
struct conv2bin<high> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};

ну, что мы получаем, двоичные литералы, которые уже оценивают полностью во время компиляции из-за "constexpr" выше. Вышеупомянутое использование трудно кодированный интервал возвращает тип. Я думаю, что можно было даже заставить его зависеть от длины двоичной строки. Это использует следующие функции для любого заинтересованного:

На самом деле, текущая соединительная линия GCC реализации variadic шаблоны и статические утверждения. Давайте надеяться, что это будет скоро поддерживать другие два. Я думаю, что C++ 1x будет качать дом.

34
ответ дан Johannes Schaub - litb 7 November 2019 в 12:00
поделиться

Один, немного ужасный способ, которым Вы могли сделать это, путем генерации.h файла с большим количеством #defines...

#define b00000000 0
#define b00000001 1
#define b00000010 2
#define b00000011 3
#define b00000100 4

и т.д. Это могло бы иметь смысл для 8-разрядных чисел, но вероятно не для 16-разрядного или большего.

, С другой стороны, делают это (подобный ответу Zach Scrivena):

#define bit(x) (1<<x)
int HAS_NUKES       = bit(HAS_NUKES_OFFSET);
int HAS_BIO_WEAPONS = bit(HAS_BIO_WEAPONS_OFFSET);
1
ответ дан Rocketmagnet 7 November 2019 в 12:00
поделиться

Следующая версия C++, C++ 0x, представит определяемые пользователем литералы. Я не уверен, будут ли двоичные числа частью стандарта, но в худшем Вы сможете включить его сами:

int operator "" _B(int i);

assert( 1010_B == 10);
4
ответ дан Motti 7 November 2019 в 12:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: