I am writing a C# program that modifies a binary file. In the file there is a byte that stores ALL the information on what a person is wearing.
Example:
1 = Hat
2 = Shoes
4 = Socks
8 = Pants
16 = Shirt
32 = Glasses
64 = Watch
128 = Earrings
Sally is wearing shoes, pants and a shirt = 2 + 8 + 16 = 26. The byte stored is 26.
Fred is wearing a hat, shoes, socks, paints, shirt, glasses and a watch: 1 + 2 + 4 + 8 + 16 + 32 + 64 = 127. The byte stored is 127
Now I want to take that number and figure out what they are wearing. A person cannot wear two of the same things, and there are only the 8 options.
You have a bit mask.
Using your 2 + 8 + 16 = 26 example, you can pull out each bit using the bitwise "and" operator &. To check if the person is wearing shoes, "and" the bit mask with 2 and check the result:
011010 = 26
& 000010 = 2 <-- bitwise "and" operator
-------------
000010 = 2
If the bitmask was 5 instead of 26, the result would be:
000101 = 5
& 000010 = 2 <-- bitwise "and" operator
-------------
000000 = 0
So take the result and check if it's greater than zero. That's it:
bool isHat = bitMask & 1 > 0;
bool isShoes = bitMask & 2 > 0;
bool isSocks = bitMask & 4 > 0;
//and so on
FYI: I'm guessing that you are setting your bit mask by adding powers of two to an accumulator like this:
byte SetWatch(byte bitMask) {
return bitMask + 64;
}
You can also use a bitwise operation to do this. Use the bitwise "or" like this:
byte SetWatch(byte bitMask) {
return bitMask | 64;
}
Use an enum with the [Flags] attribute, then use the HasFlag method to determine whether a given instance of the enum has that flag set.
https://msdn.microsoft.com/en-us/library/system.enum.hasflag(v=vs.110).aspx
You could use this technique.
Referencing your example with Sally:
26 / 2 = 13 , Remainder = 0 <-- Hat
13 / 2 = 6 , Remainder = 1 <-- Shoes
6 / 2 = 3 , Remainder = 0 <-- Socks
3 / 2 = 1 , Remainder = 1 <-- Pants
1 / 2 = 0 , Remainder = 1 <-- Shirt
You can use bit-wise operators to figure this out.
var outfit = 26; //this is the same as 2 & 8 & 16
var bIsWearingPants = ((outfit | 8) != 0);
Related
I am working with a proprietary binary messaging protocol, where in one message a single byte is used to store 3 different values, like so:
Bit
7 IsArray (1 bit)
6 ArrayLength, MSB (4 bits, max size 2^4 = 16)
5
4
3
2 DataType, MSB (3 bits, max size = 2^3 = 8)
1
0
I want to extract these three values, and store them in three different properties in an object, bool IsArray, byte ArrayLength and byte DataType. I also need to go back from these three properties to a single byte
I seldom work at this level, and things got a bit messy when I went beyond setting or getting the single bit for IsArray, to trying to set several at once. I created three different masks that I thought would help me:
var IsArrayMask = 0x80; // 1000 0000
var ArrayLengthMask = 0x78; // 0111 1000
var DataTypeMask = 0x07; // 0000 0111
Is there an elegant way to achieve what I'm going for?
Edit: With some help from #stefankmitph, I discovered I had my shifting all messed up. This is how I go from 3 properties to a single byte now:
bool IsArray = true;
byte ArrayLength = 6;
byte DataType = 3;
byte serialized = 0x00; // Should end up as 1011 0011 / 0xB3
serialized |= (byte)((IsArray ? 1 : 0) << 7 & IsArrayMask);
serialized |= (byte)(ArrayLength << 3 & ArrayLengthMask);
serialized |= (byte)(DataType & DataTypeMask);
And back again, as per the answer below:
bool isArray = (serialized & IsArrayMask) == IsArrayMask;
int arrayLength = (serialized & ArrayLengthMask) >> 3;
int dataType = (serialized & DataTypeMask);
int val = 0xBE; //f.e. 1011 | 1110
var IsArrayMask = 0x80; // 1000 0000
var ArrayLengthMask = 0x78; // 0111 1000
var DataTypeMask = 0x07; // 0000 0111
bool isArray = ((val & IsArrayMask) >> 7) == 1; // output: true
// as pointed out by #PeterSchneider & #knittl
// you can get isArray in a probably more elegant way:
isArray = (val & IsArrayMask) == IsArrayMask;
// i keep both ways in my answer, because i think
// the first one illustrates that you have to shift by 7 to get 1 (true) or 0 (false)
int arrayLength = (val & ArrayLengthMask) >> 3; // output: 7
int dataType = (val & DataTypeMask); // output: 6
I understand that:
int bit = (number >> 3) & 1;
Will give me the bit 3 places from the left, so lets say 8 is 1000 so that would be 0001.
What I don't understand is how "& 1" will remove everything but the last bit to display an output of simply "1". I know that this works, I know how to get a bit from an int but how is it the code is extracting the single bit?
Code...
int number = 8;
int bit = (number >> 3) & 1;
Console.WriteLine(bit);
Unless my boolean algebra from school fails me, what's happening should be equivalent to the following:
*
1100110101101 // last bit is 1
& 0000000000001 // & 1
= 0000000000001 // = 1
*
1100110101100 // last bit is 0
& 0000000000001 // & 1
= 0000000000000 // = 0
So when you do & 1, what you're basically doing is to zero out all other bits except for the last one which will remain whatever it was. Or more technically speaking you do a bitwise AND operation between two numbers, where one of them happens to be a 1 with all leading bits set to 0
8 = 00001000
8 >> 1 = 00000100
8 >> 2 = 00000010
8 >> 3 = 00000001
If you use mask 1 = 000000001 then you have:
8 >> 3 = 000000001
1 = 000000001
(8 >> 3) & 1 = 000000001
Actually this is not hard to understand.
the "& 1" operation is just set all bits of the value to the "0", except the bit, which placed in the same position as the valuable bit in the value "1"
previous operation just shifts the all bits to the right. and places the checked bit to the position which won't be setted to "0" after operation "& 1"
fo example
number is 1011101
number >> 3 makes it 0001011
but (number >> 3) & 1 makes it 0000001
When u right shift 8 you get 0001
0001 & 0001 = 0001 which converted to int gives you 1.
So, when a value 0001 has been assigned to an int, it will print 1 and not 0001 or 0000 0001. All the leading zeroes will be discarded.
Like the title, I don't understand why that expression is always true?
Here is the detail:
// x, y, z, t is always different with each other
int x = 1;
int y = 2;
int z = 3;
int total = (int)Math.Pow(2, x) + (int)Math.Pow(2, y) + (int)Math.Pow(2, z);
int t = 4; // or any number which is not x, y, z
int result = (int)Math.Pow(2, t) & total;
result is always = 0
Can someone explain it please?
Here is some example how to apply this expression into my code :P.
I have list of day of week. I want to pick a day to go out with my friend. If today is not picked, ill not go anywhere :D
Some pre-defined value:
Day: Mon-Tue-Wed-Thu-Fri-Sat-Sun
Value: 1-2-3-4-5-6-7
I will pick Mon, Tue and Fri save value into my DB.
Instead of saving {1, 2, 5}, ill save 38 (2^1 + 2^2 + 2^5).
If today is Tue, I will check like this: 2^2 & 38 = 4. 4 is # 0 so today is the day, go out.
If today is Wed, I will check like this: 2^3 & 38 = 0. So today isn't, go to bed
To really understand what is happening here, you must first understand binary, because what you're doing with the & is a bitwise-and.
So, in our normal way of writing numbers, we use the decimal system, or base-10, system. You count from 0 to 9 and then prepend another number to indicate an "overflow": 10. In binary, or base-2, we can only count 0 or 1, before we must prepend another number. So, to count from 0 to 4 for example, we have binary: 0 = 0, 1 = 1, 2 = 10, 3 = 11, 4 = 100. Each one of these zeros or ones are bits, which are easy for a computer to calculate with since it can represent them as a transistor switching either on or off.
What you're doing here is generating numbers that are basically 1's with a lot of zeros in binary. You'll notice that if you do 10^x (Math.Pow(10, x)) you get multiples of 10 with a lot of zeros: 10, 100, 1000, 10000, etc.
2^x (Math.Pow(2, x)) does the same thing: it generates the binary numbers 1, 10, 100, 1000, 10000. In our decimal notation those binary numbers translate to 1, 2, 4, 8, 16 respectively.
Now what the & (bitwise AND) does, is return the binary code in which all the ones on the left are also one the right. So, say you have binary: 2^1 + 2^2 + 2^3 = 1 + 10 + 100 = 111.
And you do a bitwise operation with 2^4 on the left, which is 1000. So you're asking if 1000 & 0111 (you can add as many zeros to the left of any binary code, just as you could with a decimal number: 00100 is still just one hundred). This evaluates to 0000 = 0.
You noticed that when t is either x, y, or z, it returns either x, y or z respectively, effectively acting like a filter, because, well: 0010 & 0111 = 0010 (there are both ONES in the second position). A more complex example would be 0110 1100 & 1100 0101 = 0100 0100.
There; now you can calculate your computer does :-)
If you see it as binary, and as long as x,y,z are distinct numbers, the result of;
(int)Math.Pow(2, x) + (int)Math.Pow(2, y) + (int)Math.Pow(2, z)
is an integer with bit x, y and z (and only those bits) set.
(int)Math.Pow(2, t) & total
...checks if bit t is set. As long as t is distinct from x, y, z, it won't be.
It's because:
total = 14
Math(2,4) = 16
16 and 14 = 0
it's binary operation!
16 = (10000) binary
14 = (01110) binary
no common bit between them so and will return 0. If you expected othere result maybe you wanted to do or?
16 or 14 = 30
Its a binary comparison (& compares each position in the two numbers and returns 1 if both are 1):
10000 // 16 in binary
01110 // 14 in binary
00000 // 14 & 16 = 0
Use some other value there instead, and you will get a different value. Take, for example 6 and 10:
00101 // 6 in binary
01110 // 14 in binary
00100 // 6 and 14 = 8
PS: You can experiment with this type of math using the calculator on your PC by choosing View > Programmer, and switching between Bin and Dec on the left hand side.
Think of x, y, z and t as bit positions - you're doing a bitwise & which will clear any bits which aren't set in both operands, and 2t will only have the tth bit set.
So if x, y and z are all different, 2x + 2y + 2z will have bits x, y andz set, and 2t will have bit t set... so performing a bitwise AND operation on the two results will always give 0.
Now your original claim (which didn't specify that x, y and z were different) isn't quite true, because if x and y are the same (for example) the addition can effectively give you a different bit. (Addition of integer values each of which has just a single bit set is only equivalent to bitwise-OR if the operands all have different bits set.)
For example:
int x = 2;
int y = 2;
int z = 10; // Ignore this, effectively
// 2^2 + 2^2 + 2^10 == 2^3 + 2^10
int total = (int)Math.Pow(2, x) + (int)Math.Pow(2, y) + (int)Math.Pow(2, z);
int t = 3;
int result = (int)Math.Pow(2, t) & total; // result is now 8
& Does binary AND operation and hence binary ADD of 16 and 14 is 0
10000
& 01110
-------
00000
total = 14
Math(2,4) = 16
So
(10000) // 16
(01110) // 14
(00000) // 16 & 14 = 0
(int)Math.Pow(2, t) = (2^4)base 10 = (10000)base 2
total = (2^3 + 2^2 + 2^1)base 10 = (01110)base 2
& is binary AND and can be considered as multiplication between every bits
therefore
1*0 = 0
0*1 = 0
0*1 = 0
0*1 = 0
0*0 = 0
(int)Math.Pow(2, t) & total = (10000)base 2 & (01110)base 2 = (00000)base 2 = 0
Assume we have
total1 = (10001)base 2
then
(int)Math.Pow(2, t) & total1 = (10000)base 2 & (10001)base 2 = (10000)base 2 = (16)base 10
Here you are doing a binary operation by using &.
This & is equal to bitwise AND (AND gate) . AND works like this.
When 1 & 1 =1
when 1 & 0 = 0
when 0 & 1 = 0
when 0 & 0 = 0
when matching values met it will output 1 , else it will output 0.Check how and works
1001
1110
------
1000
------
so value of binary 1000 is 8
How can I merge first n bits of a byte with last 8-n bits of another byte?
I know something like below for picking 3 bits from first and 5 from second (Which I have observed in DES encryption algorithm)
zByte=(xByte & 0xE0) | (yByte & 0x1F); But I don't know maths behind why we need to use 0XE0 and 0X1F in this case. So I am trying to understand the details with regards to each bit.
In C#, that would be something like:
int mask = ~((-1) << n);
var result = (x & ~mask) | (y & mask);
i.e. we build a mask that is (for n = 5) : 000....0011111, then we combine (&) one operand with that mask, the other operand with the inverse (~) of the mask, and compose them (|).
You could also probably do something more quickly just using shift operations (avoiding a mask completely) - but only if the data can be treated as unsigned (so Java might struggle here).
It just sounds like you don't understand how boolean arithmetic works? If this is your question it works like this:
0xEO and 0x1F are hexidecimal representations of numbers. If we convert these numbers to binary they would be:
0xE0 = 11100000
0x1F = 00011111
Additionally & (and) and | (or) are bitwise logical operators. To understand logical operators, first remember the 1 = true and 0 = false.
The truth table for & is:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
The truth table for | is:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
So let's breakdown your equation piece by piece. First we will evaluate the code in parenthesis first. We will walk through each number in binary and for the & operator if each operand has a 1 in the same bit position we will return 1. If either number has a 0 then we will return 0. After we finish the evaluation of the operands in the parenthesis we will then take the 2 resulting numbers and apply the | operator bit by bit. If either number has a 1 in the same bit position we will return 1. If both numbers have a 0 in the same bit position we will return 0.
For the sake of discussion, let's say that
xByte = 255 or (FF in hex and 11111111 in binary)
yByte = 0 or (00 in hex and 00000000 in binary)
When you apply the & and | operators we are going to compare each bit one at a time:
zByte = (xByte & 0xEO) | (yByte & 0x1F)
becomes:
zByte = (11111111 & 11100000) | (00000000 & 00011111)
zByte = 111000000 | 00000000
zByte = 11100000
If you understand this and how boolean logic works then you can use Marc Gravell's answer.
The math behind those numbers (0xE0 and 0x1F) is quite simple. First we are exploiting the fact that 0 & <bit> always equals 0 and 1 & <bit> always equals <bit>.
0x1F is 00011111 binary, which means that the first 3 bits will always be 0 after an & operation with another byte - and the last 5 bits will be the same they were in the other byte. Remember that every 1 in a binary number represents a power of 2, so if you want to find the mask mathematically it would be the sum of 2^x from x = 0 to n-1. Then you can find the opposite mask (the one that is 11100000) to extract the first 3 bit, you simply need to subtract the mask from 11111111, and you will get 11100000 (0xE0).
In java,
By using the following function we can get the first n bits of the first Byte and last 8 n bits of the second byte.
public class BitExample {
public static void main(String[] args) {
Byte a = 15;
Byte b = 16;
String mergedValue=merge(4, a, b);
System.out.println(mergedValue);
}
public static String merge(int n, Byte a, Byte b) {
String mergedString = "";
String sa = Integer.toBinaryString(a);
String sb = Integer.toBinaryString(b);
if(n>sa.length()) {
for(int i=0; i<(n-sa.length()); i++) {
mergedString+="0";
}
mergedString+=sa;
}else{
mergedString+=sa.substring(0, n);
}
if(8*n>sb.length()) {
for(int i=0; i<(8*n-sb.length()); i++) {
mergedString+="0";
}
mergedString+=sb;
}
return mergedString;
}
}
Is there any difference between Arithmetic + and bitwise OR. In what way this is differing.
uint a = 10;
uint b = 20;
uint arithmeticresult = a + b;
uint bitwiseOR = a | b;
Both the results are 30.
Edit : Small changes to hide my stupidity.
(10 | 20) == 10 + 20 only because the 1-bits do not appear in the same digit.
1010 = 10
or 10100 = 20
————————
11110 = 30
However,
11 = 3 11 = 3
or 110 = 6 + 110 = 6
—————— ——¹——————
111 = 7 1001 = 9
# ^ ^
# (1|1==1) (1+1=2)
Counterexample:
2 + 2 == 42 | 2 == 2
Bitwise OR means, for each bit position in both numbers, if one or two bits are on, then the result bit is on. Example:
0b01101001
|
0b01011001
=
0b01111001
(0b is a prefix for binary literals supported in some programming languages)
At the bit level, addition is similar to bitwise OR, except that it carries:
0b01101001
+
0b01011001
=
0b11000010
In your case, 10+20 and 10|20 happen to be the same because 10 (0b1010) and 20 (0b10100) have no 1s in common, meaning no carry happens in addition.
Try setting a = 230 and b = 120. And you'll observer the difference in results.
The reason is very simple. In the arithmentic addition operation the bit-wise add operation may generate carry bit which is added in the next bit-wise addition on the bit-pair available on the subsequent position. But in case of bit wise OR it just performs ORing which never generates a carry bit.
The fact that you're getting same result in your case is that the
numbers co-incidentally don't generate any
carry-bit during addition.
Bit-wise arithmetic Addition
alt text http://www.is.wayne.edu/drbowen/casw01/AnimAdd.gif
Bitwise OR goes through every bit of two digits and applies the following truth table:
A B | A|B
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 1
Meanwhile the arithmetic + operator actually goes through every bit applying the following table (where c is the carry-in, a and b are the bits of your number, s is the sum and c' is the carry out):
C A B | S C'
0 0 0 | 0 0
0 0 1 | 1 0
0 1 0 | 1 0
0 1 1 | 0 1
1 0 0 | 1 0
1 0 1 | 0 1
1 1 0 | 0 1
1 1 1 | 1 1
For obvious reasons, the carry-in starts-off being 0.
As you can see, sum is actually a lot more complicated. As a side effect of this, though, there as an easy trick you can do to detect overflow when adding positive signed numbers. More specifically, we expect that a+b >= a|b if that fails then you have an overflow!
The case when the two numbers will be the same is when every time a bit in one of the two numbers is set, the corresponding bit int he second number is NOT set. That is to say that you have three possible states: either both bits aren't set, the bit is set in A but not B, or the bit is set in B but not A. In that case the arithmetic + and the bit-wise or would produce the same result... as would the bitwise xor for that matter.
Using arithmetic operations to manipulate bitmasks can produce unexpected results and even overflow. For instance, turning on the n-th bit of a bitmask if it is already on will turn off the n-th bit and turn on the n+1-th bit. This will cause overflow if there are only n-bits.
Example of turning on bit 2:
Arithmetic ADD Bitwise OR
0101 0101
+ 0100 | 0100
---- ----
1001 0101 //expected result: 0101
Like-wise, using arithmetic subtract to turn off the n-th bit will fail if the n-th bit was not already on.
Example of turning off bit 2:
Arithmetic SUB Bitwise AND~
0001 0001
- 0100 &~ 0100
---- ----
0001 0001
+ 1100 & 1011
---- ----
1101 0001 //expected result: 0001
So bitwise operators are safer than arithmetic operators when you are working with bitmasks.
The following bitwise operations have analogous arithmetic operations:
Bitwise Arithmetic
Check n-th bit x & (1 << n) !(x - (1 << n))
Turn on n-th bit x |= (1 << n) x += (1 << n)
Turn off n-th bit x &= ~(1 << n) x -= (1 << n)
Try a = 1 and b = 1 ;)
+ and | have different when two bits at the same positions are 1
00000010
OR
00000010
Result
00000010
VS
00000010
+
00000010
Result
00000100