0

What I would like to accomplish is to iterate through an array of 8 integers and convert each integer into it's binary form of 8 bits. I would also like the 8 bits of each integer to be stored into a single integer array of size 64. Here is what I have so far yet I cannot seem to get the proper array.

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;                                                   

   }
} 

The array I would like to obtain would be the following. (With each bit being its own element)

{0000000000000000101111100010101000000000000000000000001000100001}
3
  • 2
    j+i, think about that for a moment, or run it step by step in your debugger and think... Commented Jan 7, 2017 at 15:02
  • @SamiKuhmonen Right, a bunch of overwriting happening. Commented Jan 7, 2017 at 15:10
  • 1
    Note that if you want to make sure that each integer is 8 bits, it would help to use std::int8_t instead of int (or, if your code may need to be ported to platforms that don't support 8-bit types, std::int_least8_t). If you specifically want integers, bits should probably be sizeof(Data) * CHAR_BIT. Otherwise, you could potentially lose data. Commented Jan 7, 2017 at 16:18

3 Answers 3

1

You must process 8 bits for each of 8 integers which indeed give 64 bits. But the loops should be:

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;
   }
}
Sign up to request clarification or add additional context in comments.

4 Comments

If you compare the generated assembly code, and what could be written directly in assembly language, that's sure! But do you really need low level optimization for this code? A common rule in high language programming is 1. use correct algorithms 2. write implementation so that they are simple to read and test without worrying for optimization 3. only if there are performances problem, profile the program to identify the pieces that require optimization - but optimization often comes at the expense of portability...
Apologies for my first comment(I misunderstood the response). This seems to work although I noticed that in the result each byte is in reverse order.
@Jcan1995: If you want the bits per bytes in the opposite order just use bits[8*j+i] = Data[j] & (1 << (7 - i)) ? 1 : 0;
I definitely need to work this out on paper for a better understanding. I highly appreciate your help.
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;
}

Try something like this where you set 8 bits at a time.

Comments

0

Note: I consider Serge's answer to be the most efficient answer, but not the easiest to reuse. As such, this answer is aimed primarily at being generic, so that it can be reused with arrays of any size (providing that the destination array is large enough).


You could also pass each value through a std::bitset, which would allow you to make a more generic version.

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

It can be used as:

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

convert_to_bits(Data, bits);

Live example here.


This, though, will typically be slightly slower than Serge Ballesta's answer. To check this, I tested it with this program, compiled five times with each of the five version macros:

[Note: All versions compared are hard-coded such that ELEMENT_SIZE == 8, so that my code would give equivalent results to Serge's answer, allowing me to just plug his answer in directly. The static_assert is removed from convert_to_bits() to accomodate this.]

Each case was compiled into a separate program, to (hopefully) minimise caching, and run 5 times in TutorialsPoint's online environment1. No optimisation options were specified.

  • Once with -DSERGE, for Serge's answer.

    sh-4.3$ g++ -DSERGE      main.cpp -std=c++14 -o serge
    
  • Once with -DTHROUGH, for convert_to_bits()'s standard use case.

    sh-4.3$ g++ -DTHROUGH    main.cpp -std=c++14 -o through
    
  • Once with -DDIRECT, for a manually-inlined version of convert_to_bits().

    sh-4.3$ g++ -DDIRECT     main.cpp -std=c++14 -o direct
    
  • Once with -DFASTDIRECT, for what should (but may not be) a more efficient manually-inlined version.

    sh-4.3$ g++ -DFASTDIRECT main.cpp -std=c++14 -o fastdirect
    
  • Once with -DNAIVE, for a naive version that doesn't use std::fill() when appropriate.

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

On average...

  • serge took 29.4 ticks.
  • through took 30.8 ticks.
  • direct took 30.6 ticks.
  • fastdirect took 32.8 ticks.
  • naive took 32.4 ticks.

1: Due to their C++ links not working for me right now, I technically used their online Java environment. This is a non-issue, however, since both their C++ and Java environments use the same sandbox, with the same tools; the only differences I've noticed are 1) which default "Hello World" program is supplied (files can freely be created and renamed), and 2) what command the "Compile" and "Execute" buttons are mapped to (which can be changed in the menu). Both environments have GCC and Javac freely available, allowing for easy execution from the Bash shell.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.