I'm working on a homework problem and I already got the answer correct, but it was the result of adding operators out of frustration so I'm hoping someone can clarify this for me.
I'm testing to see if a number is positive or negative, return 1 if x > 0, return 0 otherwise. Only using the bit operations ! ~ & ^ | + << >>
Here's my answer: !(x >> 31 | !x)
When I work this out on paper my understanding of it falls apart.
move the sign bit all the way to the right
OR that bit with !x
positive would be 0 | 1
negative would be 1 | 0
! the result, which always, not matter what, ends up as 0
!(0 | 1) = 0
!(1 | 0) = 0
What am I understanding wrong?
Where you're off is in #2:
if x is positive, x >> 31 == 0 and !x == 0 so !(0 | 0) == 1
if x is negative, x >> 31 == 1 and !x == 0 so !(1 | 0) == 0
if x is zero, x >> 31 == 0 and !x == 1 so !(0 | 1) == 0
I think you're looking for :
size_t shift = sizeof(x) * 8 - 1;
bool ans = x | ~(1 << shift);
Related
This question already has answers here:
How does this work? Weird Towers of Hanoi Solution
(3 answers)
Closed 3 years ago.
I am a beginner to C language.I have a code for towers of hanoi but can someone explain me what are these bitwise operators doing ie if value of i is 1 what will be the source and target output value ?
source = (i & i-1) % 3;
target = ((i | i-1) + 1) % 3;
i & i-1 turns off the lowest set bit in i (if there are any set). For example, consider i=200:
200 in binary is 1100 1000. (The space is inserted for visual convenience.)
To subtract one, the zeros cause us to “borrow” from the next position until we reach a one, producing 1100 0111. Note that, working from the right, all the zeros became ones, and the first one became a zero.
The & produces the bits that are set in both operands. Since i-1 changed all the bits up to the first one, those bits are clear in the &—none of the changed bits are the same in both i and i-1, so none of them is a one in both. The other ones in i, above the lowest one bit, are the same in both i and i-1, so they remain ones in i & i-1. The result of i & i-1 is 1100 0000.
1100 0000 is 1100 1000 with the lowest set bit turned off.
Then the % 3 is selecting which pole in Towers of Hanoi to use as the source. This is discussed in this question.
Similarly i | i-1 turns on all the low zeros in i, all the zeros up to the lowest one bit. Then (i | i-1) + 1 adds one to that. The result is the same as adding one to the lowest one bit in i. That is, the result is i + x, where x is the lowest bit set in i. Using our example value:
i is 1100 1000 and i-1 is 1100 0111.
i | i-1 is 1100 1111.
(i | i-1) + 1 is 1101 0000, which equals 1100 1000 + 0000 1000.
And again, the % 3 selects a pole.
A quick overview of bitwise operators:
Each operator takes the bits of both numbers and applies the operation to each bit of it.
& Bitwise AND
True only if both bits are true.
Truth table:
A | B | A & B
-------------
0 | 0 | 0
1 | 0 | 0
0 | 1 | 0
1 | 1 | 1
| Bitwise OR
True if either bit is true.
Truth table:
A | B | A | B
-------------
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 1
^ Bitwise XOR
True if only one bit is true.
Truth table:
A | B | A ^ B
-------------
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 0
~ Bitwise NOT
Inverts each bit. 1 -> 0, 0 -> 1. This is a unary operator.
Truth table:
A | ~A
------
0 | 1
1 | 0
In your case, if i = 1,
the expressions would be evaluated as:
source = (1 & 1-1) % 3;
target = ((1 | 1-1) + 1) % 3;
// =>
source = (1 & 0) % 3;
target = ((1 | 0) + 1) % 3;
// =>
source = 0 % 3;
target = (1 + 1) % 3;
// =>
source = 0;
target = 2 % 3;
// =>
source = 0;
target = 2;
Good answer above, here is a high-level approach:
i == 1:
source: (1 & 0). Are both of these values true or >= 1? No they are not. So the overall result is 0, 0 % 3 = 0.
target: ((1 | 0) + 1) % 3.
(1 | 0) evaluates to 1(true) since one of the two values on the sides of the | operator are 1, so now we have (1 + 1). so then it follows we have 2 % 3 = 2.
Source: 0, target: 2
This question already has answers here:
How do I set, clear, and toggle a single bit?
(27 answers)
Closed 5 years ago.
For example, if I want to set a bit in y at position n (in C)
y = y | (1 << n)
But if I want to delete a bit in y at position n I have to use the ~ operator after binary AND.
y = y & ~(1 << n);
My question: Why Must I use the ~ operator?
Is this because the result turns into negative area?
If you want to set a bit at third place from the right :
Y : 01001000
1 << 2 : 00000100
Y | (1 << 2) : 01001100 The | is OR, bits are set to 1 if any is 1.
If you want to remove the bit :
1 << 2 : 00000100
~(1 << 2) : 11111011 The ~ is NOT, bits are inversed
Y : 01001100
Y & ~(1 << 2) : 01001000 The & is AND, bits are set to 1 if both are 1.
I suggest you read more about Bitwise operators
No, ~ has nothing to do with interpreting the number as negative: tilde ~ operator interprets the number as a pattern of bits, which it then inverts (i.e. replaces zeros with ones and ones with zeros). In fact, if you apply ~ to an unsigned value, the result would remain positive.
Recall that 1 << k expression produces a pattern of all zeros and a single 1 at the position designated by k. This is a bit mask that can be used to force bit at position k to 1 by applying OR operation.
Now consider what happens when you apply ~ to it: all 0s would become 1s, and the only 1 would become zero. Hence, the result is a bit mask suitable for forcing a single bit to zero by applying AND operation.
The ~ operator turns all of the 0's to 1's and all of the 1's to 0's. In order to clear the bint in position n you want to and it will all ones and a zero in the nth position so shift a one to the nth position and ~ invert all the bits.
1 << n for n==3 (just an example) gives you a pattern 0000000...0001000. ~ negates the bit
pattern to 11111111....11110111. Using the bitwise AND operator (&) will
only set the required bit to 0, all other remain with the same value. It's using
the fact that for a bit b: b & 1 == b.
~ flips all bits, it has nothing to do with negative numbers.
A graphical representation for a sequence of k-bits
pos k-1 k-2 0
+---+---+-------------------+---+---+
1: | 0 | 0 | ··· | 0 | 1 |
+---+---+-------------------+---+---+
pos k-1 k-2 n n-1 0
+---+---+-----+---+---+---+-----+---+
1<<n | 0 | 0 | ··· | 1 | 0 | 0 | ··· | 0 |
+---+---+-----+---+---+---+-----+---+
pos k-1 k-2 n n-1 0
+---+---+-----+---+---+---+-----+---+
~(1<<n) | 1 | 1 | ··· | 0 | 1 | 1 | ··· | 1 |
+---+---+-----+---+---+---+-----+---+
Okay i know this is a pretty mean task from which i got nightmares but maybe ..i'll crack that code thanks to someone of you.
I want to compare if number is between 0 and 10 with bitwise operators. Thats the thing.. it is between 0 and 10 and not for example between 0 and 2, 0 and 4, 0 and 8 and so on..
Reference for number/binary representation with 0-4 bits. (little endian)
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111
Trying to figure out something like
if(((var & 4) >> var) + (var & 10))
I attempt to solve it with bitwise operators only (no addition).
The expression below will evaulate to nonzero if the number (v) is out of the 0 - 10 inclusive range:
(v & (~0xFU)) |
( ((v >> 3) & 1U) & ((v >> 2) & 1U) ) |
( ((v >> 3) & 1U) & ((v >> 1) & 1U) & (v & 1U) )
The first line is nonzero if the number is above 15 (any higher bit than the first four is set). The second line is nonzero if in the low 4 bits it is between 12 and 15 inclusive. The third line is nonzero if in the low 4 bits the number is either 11 or 15.
It was not clear in the question, but if the number to test is limited between the 0 - 15 inclusive range (only low 4 bits), then something nicer is possible here:
((~(v >> 3)) & 1U) |
( ((~(v >> 2)) & 1U) & (( ~v ) & 1U) ) |
( ((~(v >> 2)) & 1U) & ((~(v >> 1)) & 1U) )
First line is 1 if the number is between 0 and 7 inclusive. Second line is 1 if the number is one of 0, 2, 8 or 10. Third line is 1 if the number is one of 0, 1, 8 or 9. So OR combined the expression is 1 if the number is between 0 and 10 inclusive. Relating this solution, you may also check out the Karnaugh map, which can assist in generating these (and can also be used to prove there is no simpler solution here).
I don't think I could get any closer stricly using only bitwise operators in a reasonable manner. However if you can use addition it becomes a lot simpler as Pat's solution shows it.
Assuming that addition is allowed, then:
(v & ~0xf) | ((v+5) & ~0xf)
is non-zero if v is out-of-range. The first term tests if v is outside the range 0..15, and the second shifts the unwanted 11, 12, 13, 14, 15 outside the 0..15 range.
When addition is allowed and the range is 0..15, a simple solution is
(v - 11) & ~7
which is nonzero when v is in the range 0..10. Using shifts instead, you can use
(1<<10) >> v
which is also nonzero if the input is in the range 0..10. If the input range is unrestricted and the shift count is modulo 32, like on most CPUs, you can use
((1<<11) << ~v) | (v & ~15)
which is nonzero if the input is not in the range (the opposite is difficult since already v == 0 is difficult with only bitops). If other arithmetic operations are allowed, then
v / 11
can be used, which is also nonzero if the input is not in the range.
bool b1 = CheckCycleStateWithinRange(cycleState, 0b0, 0b1010); // Note *: 0b0 = 0 and 1010 = 10
bool CheckCycleStateWithinRange(int cycleState, int minRange, int maxRange) const
{
return ((IsGreaterThanEqual(cycleState, minRange) && IsLessThanEqual(cycleState, maxRange)) ? true : false );
}
int IsGreaterThanEqual(int cycleState, int limit) const
{
return ((limit + (~cycleState + 1)) >> 31 & 1) | (!(cycleState ^ limit));
}
int IsLessThanEqual(int cycleState, int limit) const
{
return !((limit + (~cycleState + 1)) >> 31 & 1) | (!(cycleState ^ limit));
}
I've got to solve a task but can't find the answer:
Compute x | y using only ~ and &
The maximum allowed operations are 8
Edit:
In twos complement and 32-bit representations of integers.
Right shifts are performed arithmetically.
By looking at the truth table of x | y you will see:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
x | y will be 1 if bothx and y are not 0. You can translate it to ~(~x & ~y):
~(~0 & ~0) = ~(1 & 1) = ~1 = 0
~(~0 & ~1) = ~(1 & 0) = ~0 = 1
~(~1 & ~0) = ~(0 & 1) = ~0 = 1
~(~1 & ~1) = ~(0 & 0) = ~0 = 1
This has already been answered, but they made no reference to De Morgan.
De Morgan's Law says that ~(~A & ~B) is equivalent to (A | B). My professor in Logic Design told us to "move bubble, change symbol" where a NOT (~) is a "bubble" and AND/OR are "symbols".
(A' & B')' -> move/distribute the "bubbles" -> (A & B) -> change the "symbol" -> (A | B).
This also works backwards, where the lack of a NOT can be treated as no bubble at all.
(A | B) -> add "bubbles" -> (A' | B')' -> change the symbol -> (A' & B')'
See De Morgan's Laws for some more information.
~ & ^ | + << >> are the only operations I can use
Before I continue, this is a homework question, I've been stuck on this for a really long time.
My original approach: I thought that !x could be done with two's complement and doing something with it's additive inverse. I know that an xor is probably in here but I'm really at a loss how to approach this.
For the record: I also cannot use conditionals, loops, ==, etc, only the functions (bitwise) I mentioned above.
For example:
!0 = 1
!1 = 0
!anything besides 0 = 0
Assuming a 32 bit unsigned int:
(((x>>1) | (x&1)) + ~0U) >> 31
should do the trick
Assuming x is signed, need to return 0 for any number not zero, and 1 for zero.
A right shift on a signed integer usually is an arithmetical shift in most implementations (e.g. the sign bit is copied over). Therefore right shift x by 31 and its negation by 31. One of those two will be a negative number and so right shifted by 31 will be 0xFFFFFFFF (of course if x = 0 then the right shift will produce 0x0 which is what you want). You don't know if x or its negation is the negative number so just 'or' them together and you will get what you want. Next add 1 and your good.
implementation:
int bang(int x) {
return ((x >> 31) | ((~x + 1) >> 31)) + 1;
}
The following code copies any 1 bit to all positions. This maps all non-zeroes to 0xFFFFFFFF == -1, while leaving 0 at 0. Then it adds 1, mapping -1 to 0 and 0 to 1.
x = x | x << 1 | x >> 1
x = x | x << 2 | x >> 2
x = x | x << 4 | x >> 4
x = x | x << 8 | x >> 8
x = x | x << 16 | x >> 16
x = x + 1
For 32 bit signed integer x
// Set the bottom bit if any bit set.
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x ^= 1; // Toggle the bottom bit - now 0 if any bit set.
x &= 1; // Clear the unwanted bits to leave 0 or 1.
Assuming e.g. an 8-bit unsigned type:
~(((x >> 0) & 1)
| ((x >> 1) & 1)
| ((x >> 2) & 1)
...
| ((x >> 7) & 1)) & 1
You can just do ~x & 1 because it yields 1 for 0 and 0 for everything else