Background:
I stumbled across bitwise operators in C here, and now I am trying to learn more about them. I searched around for exercises and came across this.
However, I'm having trouble understanding the first one "bitAnd."
The code reads:
/*
* bitAnd - x&y using only ~ and |
* Example: bitAnd(6, 5) = 4
* Legal ops: ~ |
* Max ops: 8
* Rating: 1
*/
int bitAnd(int x, int y) {
/* NOR Equivelent of AND */
return ~(~x | ~y);
}
Question:
Now, I thought that the pipe ( | ) means "or." So, why do we need ~x and ~y? Can't we just say something like:
int bitAnd(int x, int y) {
int or = x | y; //something is one number or the other
int and = ~or; // not or is the same as and
return and;
}
I wrote and ran the second code sample for myself (I have a main function to run it). I get -8 as the answer, but with values 6 and 5, you should get 4.
If you have something for "or" (the pipe operator) and "and" is just the opposite or, why do we need to use "~" on each value before we calculate ~and?
Some extra information/thoughts:
I understand that "~" flips all the bits in the value. "Or" copies the bit from either value into the other if it exists (I learned that from here). So, if I have:
6 = 00000110
and
5 = 00000101
I should get 0000111.
I only mention that to show what knowledge I have of some of the operations in case my understanding of those are wrong as well.
This is typical logic gates knowledge. The equivalent of an AND gate is NOT of a NOR b.
Let's see what happens. Suppose you have values as such:
a = 00111 => 3
b = 01001 => 9
a AND b = 00001 => 1
This is what we expect. Let's run it through your shared method, the first one:
~a = 11000 => 24
~b = 10110 => 22
~a | ~b = 11110 => 30
~(~a | ~b) = 00001 => 1 as we expect.
Now, let's run your second proposed method.
or = 01111 => 15
and = ~or = 10000 => 16.
Now you have a problem. Logically, what you do is this:
~(a | b) = ~a AND ~b.
Is it really true though?
~a = 11000 => 24
~b = 10110 => 22
~a AND ~b = 10000 => 16.
It agrees with what I said above, however, it's wrong as you can see. We want 1, not 16. The bitwise inverse "~" operator is distributive. It inverts the operations as well. So an "or" becomes an "and" and an "and" becomes an "or". I hope that clears it up.
The solution you provided uses the de Morgan's rules, which say that not (A and B) = not A or not B. Since you need to compute A and B, you negate everything once more and you get: A and B = not (not (A and B)) = not (not A or not B).
Now, you can also think in terms of truth tables to see why this is true and why your claim isn't. I won't show everything in detail, but in your solution, not (A of B) when both A and B are 0, the result is 1, which is not consistent with the and operation.
Related
when x = 1
what should
! x | x
supposed to be?
I am really confused as what I did it:
x = 1 = 01 in binary,
!x = 10
!x | x = 11 = 3in decimal.
But it should be 1. (Even try going hexadecimal (something lengthy but what I am learning as an undergrad), I got -1)
The ! is the logical negation operator. If you give it nonzero things it gives you back a zero. If you give it a zero it gives you back 1.
So
!x | x
=> !1 | 1
=> 0 | 1
=> 1
Note how this is different from the bitwise negation operator, ~. If you had used this instead of !, things would have worked out like this (assuming 8-bit values, you can scale up to 32 or 64 or whatever):
~x | x
=> ~1 | 1
=> 11111110 | 00000001
=> 11111111
=> -1
It all comes down to understanding the difference between ! and ~. It's not obvious; it's just something you have to get used to. Just as a reminder
!7 = !23423523 = !46 = !(-200) = !1 = 0
For any nonzero x, !x = 0. That's just how it is. The idea behind that is C takes 0 as false and anything else as true. So, since a value like 70343 or 1 counts as true, applying ! to it gives false, or 0.
the ! operator is for logical negation, !x is equivalent to x == 0 for both numeric and pointer types.
!x has type int and a value of 1 if x compares equal to 0 and has a value of 0 for all other cases.
I would like to ask: with A, B, and C are any binary number. After getting C = A & B (& is AND operator), is there any possibility to recover A from B and C?
I know that the information of A will be lost through the operation. Can we form a function like B <...> C = A, and how complexity it can be?
For example:
A = 0011
B = 1010
C = A & B = 0010
The 2nd bit of C is 1, i.e. 2nd bit of A and B must be 1. However, the other bits lack information to be recovered.
Thank you in advance.
No, it's not possible. You can see this from the truth table for AND:
A B C (A & B)
0 0 0
0 1 0
1 0 0
1 1 1
Suppose you know that B is 0 and C is 0. A could be either 1 or 0, so it cannot be deduced from B and C.
You can recover only bits of A that have 1s in the corresponding bits of B. For bits of B that have zeros it does not matter what A has in the corresponding position, because the bit in C would be zero anyway:
A = 1xx0x011x0
B = 1001011101
----------
C = 1000001100
Positions of A marked with x can be zeros or ones; the information in them is going to be lost either way.
Assuming you are just talking binary logic not C variables, then no.
Consider:
a=0111, b=1010 therefore c=0010
So you have b=1010, c=0010 so now how can you find a?
The left most bit in c is a 0, in b it is 1 so we know a it must be 0
The second bit in c is 0, in b it is 0 so you can't tell what it was in a (either 1 or 0 leads to a 0 in c)
At this point we've proven you can't do it.
No, because there isn't a unique solution. Any value of A that has the same bits set as B would satisfy the equation, regardless of the other bits.
This is a question about equations. It is not possible as the degree of freedom is not zero. It is the same as asking a+b = 10 -- what is a and what is b?
You can't recover A, but you can write A = (X & ~B) ^ C. Here, X can be anything (and it gives all the A's).
Of course this will work only for B and C such that C & ~B == 0.
This is a parametrized solution. Example in python
>>> A = 32776466
>>> B = 89773888
>>> C = A & B
>>> C
22020352
>>> X = 1234567890 # arbitrary value
>>> U = (X & ~B) ^ C
>>> U
1238761874
>>> U & B # same result as A & B
22020352
I am trying to combine three bit operations in one line of C. For a 8 bit char, I have to set bits 2, 4, 6; clear bits 1, 3, 7 and toggle bit 0 and 5 all in one line code of C. I could do these in three line but I cannot combine these. Below is what I have done so far:
x= x & 0xD5;
x = x | 0x51;
x = x ^ 0x84;
They give the right answer for a given value of x. But I tried
x = (x & 0xD5) | (x | 0x51) | (x ^ 0x84)
And
x = x & 0xD5 | 0x51 ^ 0x84
Those do not work. Any suggestion would be appreciated.
It's simply this
x = (((x & 0xD5) | 0x51) ^ 0x84)
Your first try is wrong, because the values of x are not updated so all the operations work on the same value, besides oring the values is not equivalent to assigning the result of the operation to x.
The second, is wrong because or operator precedence, so you just need parentheses.
Your second solution fails because of operator precedence. You can fix it this way:
x = ((x & 0xD5) | 0x51) ^ 0x84;
But there is a more efficient solution:
x = (x & (0xD5 & ~0x51)) ^ (0x84 | 0x51);
You clear the bits you want to clear and the bits you want to set and then toggle both the bits you want to toggle and the bits you want to set. It compiles to one less operation because the constant operations are folded at compile time.
I'm supposed to match the worded descriptions to the bitwise operations. W is one less than the total bits in a's and b's data structure. So if a is 32 bits long W is 31 Here are the worded descriptions:
1. One’s complement of a
2. a.
3. a&b.
4. a * 7.
5. a / 4 .
6. (a<0)?1:-1.
and here are the bitwise descriptions:
a. ̃( ̃a | (b ˆ (MIN_INT + MAX_INT)))
b. ((aˆb)& ̃b)|( ̃(aˆb)&b)
c. 1+(a<<3)+ ̃a
d. (a<<4)+(a<<2)+(a<<1)
e. ((a<0)?(a+3):a)>>2
f. a ˆ (MIN_INT + MAX_INT)
g. ̃((a|( ̃a+1))>>W)&1
h. ̃((a >> W) << 1)
i. a >> 2
I have a few of them solved namely:
a. ̃( ̃a | (b ˆ (MIN_INT + MAX_INT))) = a & b
b. ((aˆb)& ̃b)|( ̃(aˆb)&b) = a
c. 1+(a<<3)+ ̃a = 7 * a
d. (a<<4)+(a<<2)+(a<<1) = 16*a + 4*a + 2*a = 22*a
e. e. ((a<0)?(a+3):a)>>2 = (a<0)?(a/4 + 3/4) : a/4 = a/4 + ((a<0)?(3/4:0)
f. a ˆ (MIN_INT + MAX_INT) = ~a
i. a >> 2 = a/4
So basically all I need help with are g and h
g. ̃((a|( ̃a+1))>>W)&1
h. ̃((a >> W) << 1)
If you wouldn't mind could you also provide an explanation if you could?
I think this is what is going on with g:
g. ̃((a|( ̃a+1))>>W)&1 = ~((a|(two's complement of a) >>W)&1
= ~((a|sign of two's complement of a) &1 = ~(-a)&1
but this could be 1 or 0 so I don't think I did this right.
and for this one:
h. ̃((a >> W) << 1) = ~((sign of a) << 1) = ~((sign of a)*2)
and I don't know where to go from there...
Thank you for your help!!!
For g, consider that (a|~a) sets all bits to 1, so:
~((a|~a) >> W) & 1
~(all_ones >> W) & 1
~1 & 1
0
The only way adding 1 to ~a could possibly affect this result is if the addition flipped the most significant bit of ~a (due to the right shift by W). That can only happen if a is 0 or 2^W. In the latter case, we will get the same result as above because the top bit of (a|X) will always be set. However, when a is 0 ~a+1 (0's twos complement) is also 0 and the final result of the entire expression will instead be 1.
Therefore, g is 1 when a is zero, otherwise it is 0 (i.e. - g is equivalent to the C expression a == 0). That seemingly doesn't match any of your worded descriptions. Indeed, I don't see how any expression (X & 1) possibly matches any of your worded descriptions. None of your worded descriptions matches an expression that evaluates to only 0 or 1 (for all values of a, b).
For h, consider that if a is negative, then its top most bit is set. Because a is signed, right shifting it 31 positions drags the sign bit across all 32 bits of a. Then left shifting it one position sets the least significant bit to 0. Complementing that yields 1. If a is non-negative, then its top most bit is 0 and right shifting that 31 positions yields 0. Left shifting that 1 position still yields 0. Complementing that yields all bits set, which is the 2's complement rep of -1. Therefore, h is equivalent to (a < 0 ? 1 : -1) or #6 of your worded descriptions.
This seems to be the #1 thing that is asked when dealing with Remainder/Mod, and I'm kind of hitting a wall with it. I'm teaching myself to program with a textbook and a chuck of C code.
Seeing as I don't really have an instructor to say, "No, no. It actually works like this", I thought I'd try my hand here. I haven't found a conclusive answer to the mathematical part of this, though.
So... I'm under the impression that this is a pretty rare occurrence, but I'd still like to know what it is that happens underneath the shiny compiling. Plus, this textbook would like for me to supply all values that are possible when using negative remainders, per the C89 Standard. Would it be much to ask if someone could check to see if this math is sound?
1) 9%4
9 - (2) * 4 = 1 //this is a value based on x - (x/y) * y
(2) * 4 + (1) = 9 //this is a check based on (x/y) * y + (x%y) = x
2) -9%4
9 - (2) * 4 = 1; 9 - (3) * 4 = -3 //these are the possible values
(2) * 4 + (1) = 9; (3) * 4 + (-3) = 9 //these are the checks
3) 9%-4
Same values as #2??
I tried computing with negatives in the expressions, and came up with ridiculous things such as 17 and -33. Are they 1 and -3 for #3 as well??
4) -9%-4
Same as #1??
In algebraic division, negative signs "cancel". Do they do the same here, or is there something else going on?
I think the thing that gets me confused the most is the negatives. The way I learned algebra in school (5-6 years ago), they are "attached" to their numbers. In programming, since they are unary operators, is that not so? Example: When filling in the value for x on #2, x = 9 instead of x = -9.
I sincerely appreciate any help.
Here you need the mathematical definition on remainder.
Given two integer numbers m, d, we say that r is the remainder of the division of m and d if r satisfies two conditions:
There exists another integer k such that m == k * d + r , and
0 <= r < d.
For positive numbers, in C, we have m % d == r and m / d == k, just by following the definition above.
From the definition, it can be obtainded that 3 % 2 == 1 and 3 / 2 == 1.
Other examples:
4 / 3 == 1 and 5 / 3 == 1, in despite of 5.0/3.0 == 1.6666 (which
would round to 2.0).
4 % 3 == 1 and 5 % 3 == 2.
You can trust also in the formula r = m - k * d, which in C is written as:
m % d == m - (m / d) * d
However, in the standard C, the integer division follows the rule: round to 0.
Thus, with negative operands C offer different results that the mathematical ones.
We would have:
(-4) / 3 == -1, (-4) % 3 == -1 (in C), but in plain maths: (-4) / 3 = -2, (-4) % 3 = 2.
In plain maths, the remainder is always nonnegative, and less than the abs(d).
In standard C, the remainder always has the sign of the first operand.
+-----------------------+
| m | d | / | % |
+-----+-----+-----+-----+
| 4 | 3 | 1 | 1 |
+-----+-----+-----+-----+
| -4 | 3 | -1 | -1 |
+-----+-----+-----+-----+
| 4 | -3 | -1 | 1 |
+-----+-----+-----+-----+
| -4 | -3 | 1 | -1 |
+-----------------------+
Remark: This description (in the negative case) is for standard C99/C11 only. You must be carefull with your compiler version, and do some tests.
Like Barmar's linked answer says modulus in a mathematical sense means that numbers are the same class for a ring (my algebra theory is a bit rusty so sorry the terms might be a bit loosely used:)).
So modulus 5 means that you have a ring of size 5. i.e. 0,1,2,3,4 when you add 1 to 4 you are back at zero. so -9,-4,1,6,11,16 are all the same modulo 5 because they are all equivalent. This is actually very important for various algebra theorems but for normal programmers it's pretty much useless.
Basically the standards were unspecified so the modulus returned for negative numbers just has to be one of those equivalent classes of numbers. It's not a remainder. Your best bet in situations like this is to operate on absolute values when doing modulo operators if you want basic integer division. If you are using more advanced techniques (like public key encryption) you'll probably need to brush up on your math a little more.
For now I'd say still with positive ints in this case and have fun programming something interesting.