Combining 2 bits to get a single integer value

Hi, I am trying to combine two binary numbers.

For example if I have a binary value of 1 and a binary value of 1. I want an integer value of 2. I was told to use bitwise operators but i'm stumped.

Thanks in advance.


Some code...
1
2
3
4
5
6
7
8
 if ((Bitplane0_ROW[p] & (1 << N)) && (Bitplane1_ROW[p] & (1 << N)) == 0)
            {
                // Index 1 (Green)
                buf[c + 0] = (BYTE)53;
                buf[c + 1] = (BYTE)189;
                buf[c + 2] = (BYTE)104;

            }


I want to convert that if statement into a an integer index number.

I was also told that I could get rid of the if statements by using bitwise operators.
Last edited on
I'm not sure if you want to "combine" two bits by storing them as the first and second bit in an integer or if you simply want to calculate the sum?

1
2
3
4
5
6
7
8
int bit1 = 1;
int bit2 = 1;

int combined = bit1 | (bit2 << 1);
std::cout << combined << "\n"; // prints 3

int sum = bit1 + bit2;
std::cout << sum << "\n"; // prints 2 
Last edited on
Yes I am trying to combine the two bits. It works but i'm having trouble combining the bits from this statement

 
 if ((Bitplane0_ROW[p] & (1 << N)) && (Bitplane1_ROW[p] & (1 << N)) == 0)


It checks whether a bit is set or not.
That means Bitplane0_ROW[p] equals one and Bitplane1_ROW[p] equals zero.

So i want to combine the two indexes which should equal 1 in decimal.

Last edited on
Why don't you just use exclusive or?
I'm not sure.
I have two bitplanes(2bpp).
Each pixel can be 0 - 3 and I need to check each one and add their index values.

for example if...
Bitplane0 is set (=1)
Bitplane1 is set (=1)

I want to get an integer value of 3
Can't you just do a simple or ?

1
2
auto val = (Bitplane0_ROW[p] & (1 << N)) | (Bitplane1_ROW[p] & (1 << N));
// Use val as needed 



You mean something like:
 
((Bitplane0_ROW[p] & (1 << N)) >> N) | (((Bitplane1_ROW[p] & (1 << N)) >> N) << 1)

which could be simplified to:
 
((Bitplane0_ROW[p] >> N) & 1) | (((Bitplane1_ROW[p] >> N) & 1) << 1)

?

There might be easier ways to write this. I'm not the kind of person who use bitwise operations every day.
Last edited on
its better if you do not expect 2 out of it.
this is binary:
000 //0
001 //1
010 //2
011//3
...

if I had 2 set bits and wanted to track them, I would expect 1 & 1 to yield 3, so I got 011 out.

to get 2, its a sum, really. byte1 + byte2. this is a counter of how many bits were set, but which specific ones were set is LOST. You get more possible values (instead of tracking just 8 bits, a byte can track the sum of 255).

Boolean expressions are effectively a bit, and you can add them or bitwise with them. That may be useful if you have a lot of similar code to this?

some of the bit junk can be hidden by using a Std::bitset. then instead of 1 << N you can just directly refer to the bit you want, easier to read.
Last edited on
Thanks guys for the suggestions.

@Peter87

Your example worked. That's what I was wanting to do. Thanks!
I don't know what it does though...

I also need to combine 4 bits using the same method you suggested.

for example I also have this.

 
if (((Bitplane0_ROW[p] & (1 << N)) && (Bitplane1_ROW[p] & (1 << N)) == 0) && (Bitplane2_ROW[p] & (1 << N)) && (Bitplane3_ROW[p] & (1 << N)));


Again how do I combine those 4 bits into an integer.

Thanks so much.
Last edited on
I don't know what it does though...

I tried to say that :) Bit twiddling is obnoxious to read.

((Bitplane0_ROW[p] >> N) & 1) | (((Bitplane1_ROW[p] >> N) & 1) << 1)
says
shift bpr0[p] down so that the nth bit is in the 0/1 bit location and test it against 1. Or that with bpr1[p] shifted down and tested against 1, shifted up.

which is still hard to follow, it becomes this:
add bpr0[p]'s nth bit to
two times bpr1[p]'s nth bit.
because shifting up (<<) is a multiplication by a power of 2 and shifting down is division by a power of 2. so if BPR1[p]'s nth bit is 1, you get 1, shifted up one time, is in binary from 01 to 10 which is from 1 to 2 in decimal. See it? Shift again, its 100 which is 4. Multiply by 2 by shift.
likewise, the ors are similar to adding. 10 | 1 is 11 which says that 2 ored with 1 is 3, which it is. Its not exactly adding (don't make that mistake somewhere later) but you know that you are adding either 1 and 0 or 0 and 0, and for THAT it works the same.

doing this with bits is just overly complicated.
now look at it this way:
int pot[] {0,1,2,4,8,16 ...};
result = (BPR0[p] & pot[n])*1 + (PBR1[p] & pot[n])*2;
of course the *1 is useless, but its there so you can SEE what is going on.
that adds (0 or 1)*1 + (0 or 1)*2 to give 0,1,2,3 as possible results, which are in binary
00
01
10
11
... and it does it with minima bit fiddling, which can be further reduced with bitfields (then you don't need the powers of two array (pot)) as its inherent).

See if you can do the next one with these ideas (which way you implement is irrelevant, but make it so you can read it in 5 years when you come back to the code). It is just more of the same, boil down each term to zero or 1 and then set the bit it represents in the integer (1,2,4,8) to get your result.

it isnt useful here, but know that anything to the zero power is 1. this helps with c++ 0 based array indexing when doing bit stuff, you can set it so [0] is the 1 bit, [1] is the 2 bit.. representing 2 to the index. the pot array quietly uses this idea a little.
Last edited on
Cyclone wrote:
I don't know what it does though...

Do you know how the bitwise operators work? That would be the first step towards understanding...

<< is the bitwise left shift operator.
>> is the bitwise right shift operator.
& is the bitwise AND operator.
| is the bitwise OR operator.
^ is the bitwise XOR operator.

Look them up if you don't know how they work.

You might also want to read some tutorials on "bitmasks" to get a better hang on how to use them.

Cyclone wrote:
I also need to combine 4 bits using the same method you suggested.

It's only fair that I explain the code that I posted but I will leave the expansion to 4 bits for you to implement.

When looking at the following expression you can essentially think of the left part of | as the first bit and the right part as the second bit.

 
((Bitplane0_ROW[p] >> N) & 1) | (((Bitplane1_ROW[p] >> N) & 1) << 1)

I think it's easier to understand what is going on with an example so lets say
Bitplane0_ROW[p] is 1001 in binary,
Bitplane1_ROW[p] is 1100 in binary
and N is 2.

Substituting with the above values you now have the following expression:

 
((0b1001 >> 2) & 1) | (((0b1100 >> 2) & 1) << 1)

Note that 0b is the prefix that we can use to write binary literals since C++14. For clarity I have also underscored the bits that we want to extract.

The subexpressions (Bitplane0_ROW[p] >> N) and (Bitplane1_ROW[p] >> N) shifts the bit that we're interested in to the first position.

Evaluating these expressions for our example we get the following:

 
(0b0010 & 1) | ((0b0011 & 1) << 1)

Doing ... & 1 will discard (set to zero) all bits except for the first position.

After doing this for our example we get:

 
0b0000 | (0b0001 << 1)

Now we have essentially calculated all the bits but they are all at the first position so before combining them we need to "shift" them into the correct position. This is what the << is used for. Doing ... << 1 will move the bit at the first position to the second position (it actually moves all bits but since the rest are zeroes we can think of it as just moving the first bit).

After doing this for our example we get:

 
0b0000 | 0b0010

The | operator is used to combine the bits of the two values.

The final result of our example then becomes:

 
0b0010
Last edited on
Thanks Peter. I am gradually learning. Got it figured out somewhat.
Topic archived. No new replies allowed.