Explanation of Output of Bitwise operations [duplicate] - c

This question already has answers here:
What are bitwise operators?
(9 answers)
Closed 9 years ago.
void main()
{
int x=7;
printf("%d",x&(x-1));
int y=6;
printf("%d",y&(y-1));
printf("%d",y>>2);
}
When I put an odd number I get output n-1 where n is a odd number but when i put y= even number I get output 0.I am not able to understand this please help.
My second question is that when i print y>>2 that is 6>>2 I get ouput 1.Please explain me this also. I know these are bitwise operations but my concept is not clear.Thanks

Let's break each line up:
x&(x-1) => 0x111 & 0x110 => 0x110 => 6
... and:
y&(y-1)) => ox110 & 0x101 => 0x100 => 4
... and finally:
y>>2 => 0x110 >> 2 => 0x001 => 1
Remark: It's probably a good idea to review your knowledge of bitwise operations.

Bitwise operations are exactly that. you take your number and you and each bit with the other number.
What that means, is if both numbers have a 1 at the slot, than you output 1, else, you output 0
so, for your example of 7 you have
0111
0110
result:
0110 (6)
for your example of 6 you have
0110
0101
result:
0100 (4)
right shift (>>) just shifts all the bits to the right, so if you take 6
0110
and shift all the bits to the right twice, you end up with
0001
or 1

When I put an odd number I get output n-1 where n is a odd number but when i put y= even number I get output 0.I am not able to understand this please help.
With binary storage the lowest bit is always 1 for odd numbers, but since you are ANDing, you are in effect simply returning the original value-1 always (because no bits have shifted). In the case of even numbers not all of the will be 0: 8 will: 1000 & 0111 = 0. 6 will not: 0110 & 0101 => 0100 = 4.
My second question is that when i print y>>2 that is 6>>2 I get ouput 1.Please explain me >>this also. I know these are bitwise operations but my concept is not clear.Thanks
It like dividing by 2 twice. so 6->3->1.5 But the fraction part is truncated, so you are left with 1. In binary, this would be 0110 -> 0011 -> 001.1 = 1.5 (decimal) but with truncation = 0001.

Related

Diffrent usage of &- operator

Look at the following code:
#include <stdio.h>
int main()
{
int num, sum;
scanf("%d", &num);
sum = num - (num&-num);
printf("%d", sum);
return 0;
}
The line sum = num - (num& - num) returns value of the given number without the last 1 in binary format. For example if the num is equal to 6(110) it will give the value without the last 1. In this case 100 which is equal to 4.
My question is how does &- work and how could do we do the same thing in octal numeral system?
What you have here is two separate operators: the bitwise AND operator & and the unary negation operator -. So the line in question is actually:
sum = num - (num & -num);
Assuming integers are stored in two's complement representation, negating a value means inverting all bits and adding one.
In the case that num is 6, (binary 00000110), -num is -6 which is 11111010. Then performing a bitwise AND between these two values results in 00000010 in binary which is 2 in decimal, so num - (num & -num) is 6 - 2 which is 4.
There is no &- operator. num - (num&-num) is num - (num & -num), where & performs the bitwise AND of num and its negation, -num.
Consider some number in binary, say 0011 0011 1100 11002 (spaces used for easy visualization). The negative of this is −0011 0011 1100 11002. However, we commonly represent negative numbers using two’s complement, in which a power of two is added. For 16-bit formats, we add 216, which is 1 0000 0000 0000 00002. So, to represent −0011 0011 1100 11002, we use 1 0000 0000 0000 00002 + −0011 0011 1100 11002 = 1100 1100 0011 01002.
Observe what happens in this subtraction, column by column from the right:
In the rightmost column, we have 0−0, which yields 0.
The next column also has 0−0, yielding 0.
The next column has 0−1. This yields 1 with a borrow from the column to the left.
The next column has 0−1−1 (where the second −1 is the borrow). This yields 0 with another borrow.
Because the minuend (the number being subtracted from) has all zeros up to that initial 1, this borrow is never satisfied, so it propagates throughout the bits.
Thus the result is:
Starting at the right, 0s remain 0s.
The first 1 stays a 1 but starts a borrow chain.
Because of the borrow, all bits to the left of that flip from 0 to 1 or 1 to 0.
Thus the subtrahend (the number being subtracted) and the result differ in all bits to the left of the first 1. And they both have 0s to the right of the first 1. So the only bit they both have set is that first 1.
Therefore, when two’s complement is in use, the result of num & -num is the lowest 1 bit that is set in num.
Then num - (num & -num) subtracts this bit from num, leaving it as num with its lowest 1 bit changed to 0.

Bit shifting x * a number

How do you get number like -10 from these bit shifting practice problems?
From what I understand X*32 can be written as x<<5. But how are you to get numbers like x*66, or X*(-10)?
General Explanation
Bit shifting is primarily aimed to shift the binary representation of a number. It is not for multiplication.
23 = 0001 0111
23 << 1 = 0001 0111 << 1 = 0010 1110 = 46
However, as the binary representation of a number is changed, the
number it represents is also changed. This is just how computer binary system works. And thus people sometimes exploit this behavior as a "hack", mostly to speed up the computation time.
Let's try to understand it more:
Left bit-shift and right bit-shift
Now, when the number represented is of integer type, then shifting the binary representation of a number by 1 to the left will be equivalent to multiplying it by 2:
23 = 0001 0111
23 << 1 = 0001 0111 << 1 = 0010 1110 = 46 //left bit-shift by 1, number becomes doubled
Given that there is no overflow for the given data type:
255 = 1111 1111 //assuming 8-bit data type
255 << 1 = 1111 1111 << 1 = 1111 1110 = 254 //not multiplied by 2, because of overflow
While shifting integer number to the right will be equivalent as dividing it by 2 and then rounding it down:
23 = 0001 0111
23 >> 1 = 0001 0111 >> 1 = 000 1011 = 11 //right bit-shift by 1, number becomes halved, rounded down
Some use and link to multiplication and division
Since bit-shifting operation is typically less costly than multiplication, to speed things up, you will see in some program, people use left bit-shift operation (as a replacement of multiplication) when they mean to multiply it by an integer number of power of 2 (that is 2, 4, 8, 16, etc):
int a = 23;
...
a = a << 2; //=102; multiply by 4, equivalent to a = a * 4, but faster operation
Or use right bit-shift operation (as a replacement of division and rounding down) to divide it with an integer number of power of 2 (that is 2, 4, 8, 16, etc)
int a = 23;
...
a = a >> 2; //=5; divide by 4 and rounding down, equivalent to integer division a = a / 4, but faster
Concluding remarks
Note that only if you operate with number with power of 2, all the multiplications and divisions above can be replaced by left bit-shift or right bit-shift.
In your example, 66 and -10 are not integer number which of power of 2, thus you cannot "hack" the multiplication/division with binary-shifting operation.
In general, use bit-shift operation if you mean for bit-shifting, as bit-shifting has many other uses than just "hacking" for multiplication/division with integer number of power of 2. If you want to multiply or divide, be happy with just using multiplication (*) or division (/) operator.
Some additional remarks:
That being said, I would just like to add some more things regarding the bit-shift for further explanation (it won't do harm):
signed integer type can hold positive or negative number
there is a difference between logical bit-shift and arithmetic bit-shift when dealing with negative number. One will give 0 in the emptied-space after shift while the other will give 1
Hence, it probably best to note that the bit-shift is mainly used for unsigned type, such like for creating bit-masks by bit shifting. That is, unsigned is recommended to be used to avoid sign-extension surprises when you deal with negative number (right) bit-shift.

binary to int with strtol in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm extracting 8 bytes from a big-endian binary file to decode into actual readable information, the second nibble from byte 4, byte 5 and byte 6 need to be concatenated and printed as a long integer value:
example input data (in binary): 0000 0000 0101 0110 1111 1000 0101 0101 0000 0001 0011 1010 0101 0000 0000 0110
example input data (hex representation): 0x0056f855013a5006
In bold are the bits i'm intending to print as long integer.
expected output: 80464
I tried the following but the result of strtol is always 0, I tried using base 0,2,10,16 always result 0.
#include<stdio.h>
#include<stdlib.h>
int main()
{
unsigned char fromfile[8]; //contains 8 bytes from a binary file
unsigned long int output; //output to be printed
unsigned char numbers[4];
numbers[0] = fromfile[4]&0x0f;
numbers[1] = fromfile[5];
numbers[2] = fromfile[6];
numbers[3] = '\0';
output=strtol (numbers,NULL,2);
printf("%lu",output);
return 0;
}
To elaborate fromfile array contains the following:
fromfile[0]=0x00;
fromfile[1]=0x56;
fromfile[2]=0xf8;
fromfile[3]=0x55;
fromfile[4]=0x01;
fromfile[5]=0x3a;
fromfile[6]=0x50;
fromfile[7]=0x06;
Compiling this code using the gcc compiler on a centos virtual machine.
Assuming the input byte order is big-endian, you can do this:
unsigned char fromfile[8]; //contains 8 bytes from a binary file
unsigned long int output; //output to be printed
output =
(fromfile[4] & 0xf) << 16 |
fromfile[5] << 8 |
fromfile[6];
printf("%lu", output);
To explain what's happening in the expression assigned to output, let's look at bytes 4 through 6 of the input which correspond to the binary digits 23 through 0 of the desired value (because of the big endian byte order):
byte: 4 5 6
bit: 23 15 7 0
00001111 11111111 11111111
We're interested in the bits masked with 1 and not interested in bits masked with 0.
fromfile[4] & 0xf takes byte 4 and masks its value with F16 = 000011112, which is exactly the mask underneath byte 4 in the figure above, using the bitwise AND operation (&).
... << 16 shifts the result of step 1 to the left by 16 binary digit positions, which is exactly the position where we need the lower nibble of byte 4 to go according to the figure above.
fromfile[5] << 8 – similarly to step 2, this takes byte 5 and shifts it to the left by 5 positions because that's where its bits are supposed to go.
fromfile[6] doesn't perform a bit shift, because the value read from byte 6 needs to be mapped to the lowest 8 bits of the output value anyway.
So now we have three values (X, Y, and Z mark unknown bits of the values x, y, and z respectively):
0000XXXX 00000000 00000000
00000000 YYYYYYYY 00000000
00000000 00000000 ZZZZZZZZ
To assemble them into one value, we use the binary OR operation (|) twice (x | y | z):
0000XXXX YYYYYYYY ZZZZZZZZ
This is exactly how we want the bits of the input data arranged and we're done.

What does XORing for 2 decimal numbers mean? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I know that XORing 2 decimal numbers mean that, they binary representations are XORed.
But what does it mean non-mathematical sense ?
What significance does it have?
If you XOR the result with one of the original numbers, you get the other original number.
a ^ b = X
X ^ a = b
X ^ b = a
This is used commonly in cryptography and hashing algorithms.
In simple words, the XOR of two decimal means, first converting the two decimals to binary and then performing the bit-wise XOR and then again converting the result to decimal.
Let's take an example,
Suppose we wanna find out what does 3^7 results? (where ^ is symbolising XOR operation)
Step 1 : Converting the numbers from decimal to binary
3 => 0011 and 7 => 0111
Step 2 : Taking the bit-wise XOR of the two binary numbers
3 : 0011
7 : 0111
3^7 : 0100
(hint : 1^0 = 1 and 1^1 = 0^0 = 0)
Step 3 : Convert the answer to decimal
0100 => 4
Hence, the 3^7 = 4
Click here for more details.
if i correctly understand, you are searching for the physical meaning of XOR.
xor is an odd parity counter, i mean if you xor(A,B), you are counting the number of ones in each bit, if the number is odd, the xor output will be one
Ex:
3 = 0011
5 = 0101
3 ^ 5 = 0110
in the LSB there are (1 and 1) which represent two ones, and since two is even, therefore you put 0, in the next bit, there are (1 and 0) and the count of ones is one which is odd, therefore you put 1 and so on.
if you want to experiment this, try this online calculator
this is used alot in telecommunication for parity check and in error correcting algorithms, and generation of orthogonal code sequencye; see this website about CDMA for more details.
a Simple example for parity checking, assume we send 8 Bits, 7 Bits data and 8th bit is parity check.
we send :
0110011X: X in this case is the parity checker, is 0 because we have 4 ones and 4 is even.
if there is a mistake in the data tranmitted and we receive for example this
11100110: Number of ones in the Byte Stream is 5 with a mistake in MSB. 5 should produce a parity bit of 1 because 5 is odd, but since the parity is 0, this means there is a mistake in the data transmitted. This is the simplest parity check used in serial data transfer. Error Correcting codes build on it.

When making binary masks for working and isolating bits and bytes, what's the fastest way to convert from Binary to Hex?

Assume I have the following binary string:
110110010110
From which I need only the 4th 5th and 6th bits, we've learned to use a mask like this
000000111000
So with the binary & operation I will get the bits I wanted and all I have left to do is shift them to the right.
Since C does not work with plain binary numbers we were told it's easiest to convert the binary mask string to a hexadecimal number. My lecturer used a super quick method to convert a binary string to a hexadecimal number.
What is the easiest and correct way to create those masks?
Each set of four bits corresponds to one hex 'digit'. Learn those, then just start converting blocks of four from right to left. (If you're converting a bit string that's not a multiple of four bits, then just add zeros to the left end until it is for the last conversion.)
0000 : 0x0
0001 : 0x1
0010 : 0x2
0011 : 0x3
0100 : 0x4
0101 : 0x5
0110 : 0x6
0111 : 0x7
1000 : 0x8
1001 : 0x9
1010 : 0xA
1011 : 0xB
1100 : 0xC
1101 : 0xD
1110 : 0xE
1111 : 0xF
For string to string? Grab 4 bits, find the number (0-15) then use as index for a table lookup. For a mask:
hex_digit = val & 0x0F;
Shift down 4 bits with:
val = val >> 4;
In my opinion, it would be helpful to cut your big string into smaller pieces of four bits, starting from the end (least significant bit). For example, your binary number 110110010110 could be written as 1101 1001 0110. If you have a number that can't be properly cut into pieces of four bits, say 1000011010, you should write it as 10 0001 1010.
Now, it's much more simple. In hexadecimal notation, 0 is 0 and f is 15. You start counting from zero, but instead of using 10 symbols, you now use 16. So it goes 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f.
You can replace each group of bits with its hexadecimal symbol! In your example (i.e. 1101 1001 0110) it would be d96, while in my example (i.e. 10 0001 1010) it would be 21a. For every one you find in a binary string, you add 2 ^ (position - 1) to your result, where position = 1 for the least significant bit. For example in 0110 you have 1 in position 2 (i.e. 2 ^ (2 - 1) = 2 ^ 1 = 2) and in position 3 (i.e. 2 ^ (3 - 1) = 2 ^ 2 = 4), so it is 2 + 4 = 6. Now, simply prepend 0x to tell the compiler that what follows is a Hexadecimal number and it becomes 0xd96.
In any case, writing a number as it is means it is in decimal notation, prepending a 0 suggests it is octal and prepending a 0x suggests it is a hexadecimal.
I hope this helps! :D

Resources