2017-01-07 6 views
0

То, что я хотел бы выполнить, - это перебрать массив из 8 целых чисел и преобразовать каждое целое число в его двоичную форму из 8 бит. Я также хотел бы, чтобы 8 бит каждого целого числа были сохранены в один целочисленный массив размером 64. Вот что я до сих пор пока не могу получить надлежащего массива.Как преобразовать массив целых чисел в массив бит?

int Data[8] = {0,0,190,42,0,0,2,33}; 

int bits[64]; 

for(int j = 0; j < 64;j++){ 
    for(int i = 0; i < 8;++i){                 

     bits[j+i] = Data[i] & (1 << i) ? 1 : 0;             

    } 
} 

Массив, который я хотел бы получить, будет следующим. (С каждым битом является его собственный элемент)

{0000000000000000101111100010101000000000000000000000001000100001} 
+2

'j + i', подумайте об этом на мгновение или запустите его шаг за шагом в своем отладчике и подумайте ... –

+0

@SamiKuhmonen Правильно, куча перезаписи происходит. – Jcan1995

+1

Обратите внимание, что если вы хотите, чтобы каждое целое число составляло 8 бит, это помогло бы использовать 'std :: int8_t' вместо' int' (или, если ваш код, возможно, потребуется портировать на платформы, которые не поддерживают 8-битные типы, 'std :: int_least8_t'). Если вы специально хотите целые числа, 'bits' должно быть, вероятно,' sizeof (Data) * CHAR_BIT'. В противном случае вы можете потерять данные. –

ответ

1

Вы должны обработать 8 бит для каждого из 8 целых чисел, которые действительно дают 64 бита. Но петли должны быть:

for(int j = 0; j < 8;j++){ // loop on integers 
    for(int i = 0; i < 8;++i){ 
     bits[8*j+i] = Data[j] & (1 << i) ? 1 : 0; 
    } 
} 
+0

Если вы сравните сгенерированный код сборки и что может быть написано непосредственно на ассемблере, это обязательно! Но вам действительно нужна низкая оптимизация уровня для этого кода? Общим правилом в языковом программировании является 1. использование правильных алгоритмов. 2. Запишите реализацию, чтобы они были просты в чтении и тестировании, не беспокоясь о оптимизации. 3. Если есть проблемы с исполнением, профайл программы для определения частей, требующих оптимизации - но оптимизация часто происходит за счет переносимости ... –

+0

Извинения за мой первый комментарий (я неправильно понял ответ). Кажется, что это работает, хотя я заметил, что в результате каждый байт находится в обратном порядке. – Jcan1995

+0

@ Jcan1995: Если вы хотите, чтобы бит в байтах в противоположном порядке, используйте 'bits [8 * j + i] = Data [j] & (1 << (7 - i))? 1: 0; ' –

0
#include <cstdint> 

int main() 
{ 
    uint64_t Data[8] = { 0,0,190,42,0,0,2,33 }; 
    uint64_t bits = 0; 

    for (int i = 0; i < 8; i++) 
    { 
     bits |= ((Data[i] & 0xFF) << (i * 8)); 
    } 
    return 0; 
} 

Попробуйте что-то вроде этого, где вы установили 8 бит за один раз.

0

Примечание: Я считаю, что самый эффективный ответ - Serge's answer, но не самый простой для повторного использования. Таким образом, этот ответ ориентирован прежде всего на то, чтобы быть общим, чтобы его можно было повторно использовать с массивами любого размера (при условии, что массив назначения достаточно велик).


Вы также могли бы пройти каждое значение через std::bitset, что позволит вам сделать более общий вариант.

template<typename FromT, size_t FromSZ, typename ToT, size_t ToSZ> 
void convert_to_bits(const FromT (&from_arr)[FromSZ], ToT (&to_arr)[ToSZ]) { 
    static_assert(ToSZ >= ((sizeof(FromT) * CHAR_BIT) * FromSZ), 
        "Destination array must have enough elements to contain all bits of source array."); 

    // Helper value, will be optimised out. 
    constexpr size_t ELEMENT_SIZE = sizeof(FromT) * CHAR_BIT; 

    // Handles bit manipulation cleanly. 
    std::bitset<ELEMENT_SIZE> temp[FromSZ]; 

    // Populate temp. 
    for (size_t i = 0; i < FromSZ; i++) { temp[i] = from_arr[i]; } 

    // Fill destination array, one "row" (value in source array) at a time. 
    for (size_t i = 0; i < FromSZ; i++) { 
     size_t row = i * ELEMENT_SIZE; 
     using std::fill; 

     if (temp[i].none()) { 
      // Row is all 0s, fill its part of destination array appropriately. 
      fill(&to_arr[row], &to_arr[row + (ELEMENT_SIZE - 1)], 0); 
     } else if (temp[i].all()) { 
      // Row is all 1s, fill its part of destination array appropriately. 
      fill(&to_arr[row], &to_arr[row + (ELEMENT_SIZE - 1)], 1); 
     } else { 
      // Row is mixed, do it one bit at a time. 
      for (size_t j = 0; j < ELEMENT_SIZE; j++) { 
       to_arr[row + j] = temp[i][j]; 
      } 
     } 
    } 
} 

Он может быть использован как:

int Data[8] = {0,0,190,42,0,0,2,33}; 
int bits[8 * (sizeof(int) * CHAR_BIT)] = {0}; 

convert_to_bits(Data, bits); 

Живой пример here.


Это, однако, как правило, будет немного медленнее, чем Serge Ballesta's answer. Чтобы проверить это, я проверил его с this program, составленный в пять раз с каждой из пяти версий макросов:

[Примечание: Все версии по сравнению жестко закодированы такие, что ELEMENT_SIZE == 8, так что мой код даст эквивалентные результаты для Serge ответ, позволяя мне просто подключить его ответ напрямую. static_assert удаляется из convert_to_bits() для размещения этого.]

Каждый случай был собран в отдельную программу, чтобы (надеюсь) свести к минимуму кэширование, и запустить 5 раз в TutorialsPoint's online environment . Параметры оптимизации не заданы.

  • Один раз с -DSERGE, для ответа Сержа.

    sh-4.3$ g++ -DSERGE  main.cpp -std=c++14 -o serge 
    
  • После того, как с -DTHROUGH для convert_to_bits() «s стандартного использования.

    sh-4.3$ g++ -DTHROUGH main.cpp -std=c++14 -o through 
    
  • После того, как с -DDIRECT, для вручную встраиваемой версии convert_to_bits().

    sh-4.3$ g++ -DDIRECT  main.cpp -std=c++14 -o direct 
    
  • После того, как с -DFASTDIRECT, для того, что должно (но не может быть) более эффективным вручную встраиваемой версии.

    sh-4.3$ g++ -DFASTDIRECT main.cpp -std=c++14 -o fastdirect 
    
  • После того, как с -DNAIVE для наивной версии, которая не использует std::fill() при необходимости.

    sh-4.3$ g++ -DNAIVE  main.cpp -std=c++14 -o naive 
    

В среднем ...

  • serge взял 29,4 тиков.
  • through взял 30,8 клещей.
  • direct взял 30,6 клещей.
  • fastdirect взял 32,8 клещей.
  • naive взял 32,4 клещей.

1: Из-за их связи C++ не работает для меня прямо сейчас, я технически использовал их онлайновую среду Java. Однако это не проблема, так как в среде C++ и Java используется одна и та же песочница с теми же инструментами; единственные отличия, которые я заметил, - это 1), по которым предоставляется программа «Hello World» (файлы можно свободно создавать и переименовывать), и 2) какую команду нажимают кнопки «Скомпилировать» и «Выполнить» (которые могут быть изменено в меню). В обеих средах доступны GCC и Javac, что позволяет легко выполнять их из оболочки Bash.