2017-01-07 7 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 비트인지 확인하려면 'int'대신'std :: int8_t'를 사용하는 것이 좋습니다 (또는 코드를 지원하지 않는 플랫폼으로 포팅해야 할 수도있는 경우 8 비트 타입,'std :: int_least8_t'). 특별히 정수를 원하면'bits'는'sizeof (Data) * CHAR_BIT'이어야합니다. 그렇지 않으면 잠재적으로 데이터가 손실 될 수 있습니다. –

답변

1

실제로 64 비트를 제공하는 8 개의 정수마다 8 비트를 처리해야합니다. 그러나 루프는해야한다 :

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을 통해 각 값을 전달할 수 있습니다.

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 :

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]; 
      } 
     } 
    } 
} 

이로 사용할 수 있습니다.


이것은 일반적으로 Serge Ballesta's answer보다 약간 느립니다.

는 [주 : 비교 모든 버전은 하드 코딩 내 코드에 해당하는 결과를 제공 할 수 있도록,되도록 ELEMENT_SIZE == 8입니다 방탄복의이를 확인하기 위해, 나는 다섯 개 가지 버전 매크로의 각각 다섯 번, this program으로 테스트 컴파일 대답을하면, 직접 대답을 입력 할 수 있습니다. static_assert은이를 수용하도록 convert_to_bits()로부터 제거된다.]

은 각 경우에, 별도의 프로그램으로 컴파일 (희망) 캐시를 최소화하며 TutorialsPoint's online environment1 5 번 실행. 최적화 옵션이 지정되지 않았습니다.

  • 한 번 -DSERGE으로, Serge의 대답에 대해. convert_to_bits()의 표준 사용 사례에 대한 -DTHROUGH에 한 번

    sh-4.3$ g++ -DSERGE  main.cpp -std=c++14 -o serge 
    
  • . convert_to_bits()의 수동 인라인 버전 -DDIRECT에 한 번

    sh-4.3$ g++ -DTHROUGH main.cpp -std=c++14 -o through 
    
  • .(하지만하지 않을 수 있습니다)해야하는지에 대한 -DFASTDIRECT에 한 번

    sh-4.3$ g++ -DDIRECT  main.cpp -std=c++14 -o direct 
    
  • ,보다 효율적인 수동으로 인라인 버전. -DNAIVE에 한 번

    sh-4.3$ g++ -DFASTDIRECT main.cpp -std=c++14 -o fastdirect 
    
  • , 적절한 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 셸에서 쉽게 실행할 수있다.