I need to determine if a signed 32 bit number is a power of two. So far I know the first thing to do is check if its negative since negative numbers cannot be powers of 2.
Then I need to see if the next numbers are valid etc... SO I was able to write it like this:
// Return 1 if x is a power of 2, and return 0 otherwise.
int func(int x)
{
return ((x != 0) && ((x & (~x + 1)) == x));
}
But for my assignment I can only use 20 of these operators:
! ~ & ^ | + << >>
and NO equality statements or loops or casting or language constructs.
So I am trying to convert the equality parts and I know that !(a^b) is the same as a == b but I cant seem to figure it out completely. Any ideas on how to covert that to the allowed operators?
Tim's comment ashamed me. Let me try to help you to find the answer by yourself.
What does it mean that x is power of 2 in terms of bit manipulation? It means that there is only one bit set to 1. How can we do such a trick, that will turn that bit to 0 and some other possibly to 1? So that & will give 0? In single expression? If you find out - you win.
Try these ideas:
~!!x+1 gives a mask: 0 if x==0 and -1 if x!=0.
(x&(~x+1))^x gives 0 if x has at most 1 bit set and nonzero otherwise, except when ~x is INT_MIN, in which case the result is undefined... You could perhaps split it into multiple parts with bitshifts to avoid this but then I think you'll exceed the operation limit.
You also want to check the sign bit, since negative values are not powers of two...
BTW, it sounds like your instructor is unaware that signed overflow is UB in C. He should be writing these problems for unsigned integers. Even if you want to treat the value semantically as if it were signed, you need unsigned arithmetic to do meaningful bitwise operations like this.
First, in your solution, it should be
return ((x > 0) && ((x & (~x + 1)) == x));
since negative numbers cannot be the power of 2.
According to your requirement, we need to convert ">", "&&", "==" into permitted operators.
First think of ">", an integer>0 when its sign bit is 1 and it is not 0; so we consider
~(x >> 31) & (x & ~0)
this expression above will return a non zero number if x is non-positive. Notice that ~0 = -1, which is 0x11111111. We use x & ~0 to check if this integer is all 0 at each digit.
Secondly we consider "&&". AND is pretty straight forward -- we only need to get 0x01 & 0x01 to return 1. So here we need to add (!!) in front of our first answer to change it to 0x01 if it returns a nonzero number.
Finally, we consider "==". To test equity of A and B we only need to do
!(A ^ B)
So finally we have
return (!!(~(x >> 31) & (x & ~0))) & (!((x&(~x+1)) ^ x))
It seems that it's a homework problem. Please don't simply copy and paste. My answer is kind of awkward, it might be improved.
Think about this... any power of 2 minus 1 is a string of 0s followed by a string of 1s. You can implement minus one by x + ~0. Think about where the string of 1s starts with relation to the single 1 that would be in a power of 2.
int ispower2(int x)
{
int ispositive= ! ( (x>>31) ^ 0) & !!(x^0);
int temp= !((x & ~x+1) ^ x);
return temp & ispositive;
}
It is interesting and efficient to use bitwise operators in C to solve some problems. In this question, we need to deal with two checks:
the sign check. If negative, return 0; otherwise return 1;
! (x >> 31 & ox1) & !(!x)
/* This op. extracts the sign bit in x. However, the >> in this case will be arithmetic. That means there will be all 1 before the last bit(LSB). For negative int, it is oxFFFFFFFF(-); otherwise, oxFFFFFFFE(+). The AND ox1 op. corrects the >> to ox1(-) or ox0(+). The Logical ! turns ox1(-) and ox0 (+) into 0 or 1,respectively. The !(!x) makes sure 0 is not power(2)*/
the isPower(2) check. If yes, return 1; otherwise 0.
!( x & (~x + ox1) ^ x )
/* This op. does the isPower(2) check. The x & (~x + ox1) returns x, if and only if x is power(2). For example: x = ox2 and ~x + ox1 = oxFFFFFFFE. x & (~x + ox1) = ox2; if x = ox5 and ~x + ox1 = oxFFFFFFFB. x & (~x + ox1) = ox1. Therefore, ox2 ^ ox2 = 0; but ox5 ^ ox1 = ox4. The ! op turn 0 and others into 1 and 0, respectively.*/
The last AND op. between 1 and 2 checks will generate the result of isPower(2) function.
Related
I want to verify two bits (for example the bit number 3 and 5) values of a uint8
if their value is 0, I want to return 1
uint8 a;
if ((a & !(1<<3)) && (a & !(1<<5)))
{
Instructions..
}
Is this code correct ?
No, your code won't work in way that you want. ! operator results only in 0 or 1 and info about actual non-zero bit is lost anyway. You may use something like this:
if(!(a & ((1 << 3) | (1 << 5))) {
/* ... */
}
At first stage you are creating mask with | operator. This mask has non-zero bits only at positions that you are interested in. Then this mask is combined with tested value via &. As result you get 0 only if value has zero bits at tested positions. And then just inverse 0 to 1 with ! to obtain true condition.
It is not correct.
The ! operator is boolean NOT, not a bitwise NOT.
So, if you want to check if bits 3 & 5 are both zeroes you should write:
uint8 a;
...
if (!(a & (1<<3)) && !(a & (1<<5)))
{
Instructions..
}
Further optimisation of the expression in if is possible.
This is trivial if you don't attempt to write it as a single, messy expression. There is no advantage of doing so - contrary to popular belief, mashing as many operators into a single line is actually very bad practice. It destroys readability and you gain no performance benefits what-so-ever.
So start by creating a bit mask:
uint8_t mask = (1<<3) | (1<<5);
(The parenthesis are actually not needed, but not everyone can cite the C operator precedence table in their sleep, so this is recommended style.)
Then check the data against the mask:
if(data & mask) // if any bit contains value 1
return 0;
else // if no bit contains value 1
return 1;
Which, if you will, can be rewritten as a boolean expression:
return !(data & mask);
The complete function could look like this:
bool check_bits (uint8_t data)
{
uint8_t mask = (1<<3) | (1<<5);
return !(data & mask);
}
Your expression is false, you should not negate the masks this way and you must ignore other bits so don't use a negation. Simply:
(a & (1<<3)) + (a & (1<<5))
gives 0 if both are 0s.
Assuming that a actually is initialized, then the expression will not work as you expect. The logical not operator ! gives you a one or a zero (boolean true or false), which you then use in a bitwise and operation. That will not give you the correct result.
I suppose you mean to use the bitwise complement operator ~ instead, as in ~(1 << 3). Not that it would work anyway, as that will just check that any of the other bits in a is non-zero.
Instead check if the bit is one, and then turn around the logic using the logic not operator !, as in !(a & 1 << 3).
No. ! operator does logical negation, and since 1<<3 is not zero, !(1<<3) is zero. It means a & !(1<<3) will always be zero and therefore the condition will never be true.
I think masking is one of good ways to do what you want to do.
uint8 a;
/* assign something to a */
return (a & ((1 << 3) | (1 << 5))) == 0;
a & ((1 << 3) | (1 << 5)) is a value in which the 3rd and 5th bit (0-origin) of a keep their original value and all other bits is turned to zero. Checking if the value is zero means checking if all of the bits to check are zero while not careing other bits. == operator will return 1 if two operands are equal and 0 otherwise.
If you want to test for some combination of BIT_A and BIT_B (or whatever number of bits you can have) You can do this:
#define BIT_A (1 << 3)
#define BIT_B (1 << 5)
...
#define BIT_Z (1 << Z)
...
/* |here you put all bits |here you put only the ones you want set */
/* V V */
if (a & (BIT_A | BIT_B | ... | BIT_Z) == (BIT_A | ... | BIT_I | ...))
{
/* here you will know that bits BIT_A,..., BIT_I,... will **only**
* be set in the mask of (BIT_A | BIT_B | ... | BIT_Z) */
}
as with a & (BIT_A | BIT_B | ... ) you force all bits not in the set to be zero, so only the bits in the set will conserve their values. With the second mask, you generate a bitmap with only the bits of the set you want to be set (and of course the bits that are not in the set forced zero) so if you compare both values for equalness, you'll get the expected result.
NOTE
As an answer to your question, the particular case in which you want all the bits equal to one, is to make both masks equal. For your case, you want to check if both bits are zero, then your test is (the second mask has no bits set, so it is zero):
if (a & ((1 << 3) | (1 << 5)) == 0) { ...
(All bits in the second mask are zero as the required mask, and both, the third and the fifth bits are set in the first mask) This can be written in a more compact form as (you can see it written as):
if (!(a & 0x28)) { /* 0x28 is the octal for 00101000, with the bits you require */
WHY THE CODE YOU WROTE IS NOT CORRECT
First you mix logical operators like ! with bitmasks, making !(1<<3)to eval to 0 (1<<3 is different of 0 so it is true, negating gives 0) and the same for the !(1<<5) subexpression. When you mask a with those values makes you get a & 0 ==> 0 and a & 0 ==> 0 and anding both together gives 0 && 0 ==> 0. So the result value of your expression is 0 -- false always, independent of the original value of a.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've tried to find an algorithm which...
...returns 1 (if x == 2^n) //2^n is "2 to the power of n" not xor.
...returns 0 (if x != 2^n && x == 0) //2^n is "2 to the power of n" not xor.
I may assume that my machine works with:
two's complement,
32-bit representation of integers,
performs right shifts arithmetically,
unpredictable behavior when shifting an integer by more than the word size.
I'm also only allowed to use the following operators: ! ~ & ^ | + << >>
This is what I got so far:
int isPower2(int x) {
return ( !(x ^ (x & ~x+1)) )); // But this returns 1 if x == 0.
}
To get this code working correctly I changed it to ((x ^ 0) && ( !(x ^ (x & ~x+1). But I'm not allowed to use &&. So I have to build an AND out of NANDs using the ~ and & operator.
But I know, that I can build every possible GATE with NANDs (I only need ~ and & for it).
So... X AND Y is equal to (X NAND Y) NAND (X NAND Y) - NAND logic
X := (x ^ 0)
Y := !(x ^ (x & ~x+1))
But changing ((x ^ 0) && ( !(x ^ (x & ~x+1)) )) into ~(~((x ^ 0) & !(x ^ (x & ~x+1)) ) & ~((x ^ 0) & !(x ^ (x & ~x+1)))) doesn't seem to do the trick.
Edit: I added some extra information, hope my problem is clearer now.
Question is terrible written but quite interesting
Try this
int isPower2(int x) {
return !(x^(x&~x+1))&!!x;
}
More readable version + explanation
int isPower2(int x) {
return
(!(
x^(
x&((~x)+1)
)
))
&
(!!x);
}
This code bases on fact that powers of 2 have single 1 in binary representation
x&((~x)+1) - will give x if x is power of 2 or 1 otherwise
1 (0001) -> 0001 & (1110+1) -> 0001 & 1111 -> 0001
2 (0010) -> 0010 & (1101+1) -> 0010 & 1110 -> 0010
3 (0011) -> 0011 & (1100+1) -> 0011 & 1101 -> 0001
4 (0100) -> 0100 & (1011+1) -> 0100 & 1110 -> 0100
5 (0101) -> 0101 & (1010+1) -> 0101 & 1011 -> 0001
We XOR the result with x, since we got x for powers of 2 and 1 we get here 0 only for powers of 2.
Later we logically invert result giving us 1 for powers of 2.
To eliminate 0 case we AND with twice logically inverted x
Let me try to at least parse a few of the expressions out here. First we have !(x ^ (x & ~x+1)) ). The right hand side of the inner & is the definition of a negation in two's complement. For that to have a common bit set with the original value, it must have been carried there in the addition, which means all the less significant bits were 0 before the complement. In effect this finds the least significant bit that was set in x. The ^ (exclusive or) operator then toggles any bit that was set to begin with; if the bit we found was the only one in there, the result is 0. However, it is also 0 if the input was 0, as no bit was ever found set. The logical not (!) thus produces x==0 || isPowerOf2(x). That's what the comment notes; the intent is apparently to remove the case of x==0.
That is the function of the change ((x ^ 0) && ( !(x ^ (x & ~x+1). The new part checks that any bit was set in x in the first place. x^0 is equal to x for any x, so the new xor has no effect, but && is a logical operator and therefore does not care which particular bits are set. However, all logical operators except ! are excluded for this exercise.
The complex attempt at converting x&&y into (x nand y) nand (x nand y) misses the point that the problem is with bitwise versus logical operators. The ! present in the expression produces only 1 or 0, destroying the information of which higher bits were set; therefore it doesn't line up with x anymore. In fact ! is the only operator in our allowed set with this reduction property.
There is an alternate method to produce a reduction with the allowed operators, hinted at in the notes on word width and shift behaviour; you can construct a wide bitwise operation by repeated shifting to line up all bits. While useful if you want to build a parity function or similar, this requires many operations and is error-prone to type out.
If we know the operands are only 0 or 1, the effects of bitwise or logical operators except for complement is equivalent. Since ! does produce those values, we can convert x&&y into !!x & !!y (ignoring the shortcutting, since we're not dealing with side effects). In this case we already had a ! on the right side, so we can remove two !s.
I need to convert from two's complement to sign-magnitude in C using only the operators
! ~ & ^ | + << >>
My approach is to find sign:
int sign = !(!(a>>31));
basically, if sign == 1 . I want to flip the number and add 1 else just want to display the number.
The thing is I can't use any loops, if statements etc.
This is what I'm working on:
int s_M = ((((a+1)>>31)^sign)+1)&sign;
any suggestions?
From http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
int const mask = v >> 31;
unsigned int r = (v + mask) ^ mask;
Gives the absolute value (magnitude). If you wish to add the sign bit back simply mask and or the 32nd bit:
unsigned int s_M = r | (v & 0x80000000);
Or if you're looking for a one liner:
unsigned int s_M = ((v + (v >> 31)) ^ (v >> 31)) | (v & 0x80000000);
When you're converting from 2 complement, you should subtract 1, not add.
I'm not entirely sure what the output should be, but to obtain the magnitude you can do something like this:
int m = (a^(a>>31)) + sign;
Basically, shifting a negative number 31 bits to the right will make it all 1's, or 0xffffffff, which you can then use to xor the input number and make it positive. As you correctly noted sign needs to be added then for the correct result in that case.
If the input number was positive to begin with, the shift results in a zero and so the xor does nothing. Adding sign in that case also doesn't do anything, so it results in the input number.
To get the last bit you could use mask operation
int last_bit = 32 bit integer & 0x80000000
o/p may be 0 or 0x80000000
if it is 0 just display the given number else you have to perform the following operations to represent in signed magnitude
1) Subtract 1 from the number
2) perform 1s complement on the resultant ( that is negation ~)
3) Set the last bit of the resultant number
I mean ( ~ (num -`1) ) | 0x7fffffff
since your restricted not to use - operator. Perform the 2's complement on -1 and add it to the num.
To put it simple in one line
num & 0x80000000 ? printf("%d",(~(num+((~1)+1))) | 0x7fffffff) : printf("%d",num) ;
Why does the following C code not work for returning -1 for negative numbers, 0 for 0s, and 1 for positive numbers?
(((x >> 31) ^ -1) + 1) | (!x ^ 1);
Specifically, when I pass in negative numbers, it returns 1. It seems like if I have a negative number, though (i.e., the the least significant bit is a 1 after the 31 bit shift), XORing it with -1 will give me -2 (i.e., all 1s and a 0 in the least significant bit location), and adding 1 would make it -1.
According to the C99 standard, the result of x >> n if x is negative is implementation defined. So the reason you are having a problem depends on your compiler and architecture.
However, it's most likely that the x is sign extended when you shift it i.e. the top bit is repeated to keep the sign the same as the operand. This is what happens with my compiler. So for any negative number, x >> 31 is -1. Also, for any non zero number !x is 0 (i.e. false). This applies assuming x is a 32 bit integer. If you make x an unsigned int, it should work, but consider the following alternative:
(x < 0) ? -1 : ((x > 0) ? 1 : 0)
which I think is a bit less cryptic.
And here is a program that you can use to see what your expression is doing
#include <stdio.h>
#define EVALUATE(x) printf("%s = %d\n", #x, x)
int main(int argc, char** argv)
{
unsigned int x = 51;
EVALUATE(x >> 31);
EVALUATE(((x >> 31) ^ -1));
EVALUATE(((x >> 31) ^ -1) + 1);
EVALUATE(!x);
EVALUATE(!x ^ 1);
EVALUATE((((x >> 31) ^ -1) + 1) | (!x ^ 1));
return 0;
}
>> will generally do arithmetic shift on signed data, so ((-1) >> 31) == (-1), contrary to your assumption. As pointed out by others, this is not guaranteed by the standard, but it is most likely true on modern systems. In any case, be careful with this type of bit twiddling. If portability is a concern or speed is not, you should do it a different way. See Is there a standard sign function (signum, sgn) in C/C++? for some ideas.
I am attempting to determine if I can compute the sum of two 32 bit integers without overflow, while making use of only certain bitwise and other operators. So, if the integers x and y can be added without overflow, the following code should return 1, and 0 otherwise.
(((((x >> 31) + (y >> 31)) & 2) >> 1))
However, it returns 0 when it should be 1 and vice versa. When I employ the logical NOT (!) operator, or bitwise XOR (^) with 0x1, it does not fix the issue.
!(((((x >> 31) + (y >> 31)) & 2) >> 1))
(((((x >> 31) + (y >> 31)) & 2) >> 1) ^ 0x1)
^ these don't work.
Thanks in advance.
This is a bit cleaner:
~(x & y) >> 31
Update
kriss' comment is correct. all this code does is check that the two MSBs are both set.
I was just looking at kriss' answer, and it occurred to me that the same thing can be done using only a single addition, plus bitwise operators, assuming unsigned ints.
((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF)) & 0x80000000 & (x | y)
The first parenthesised section sets both MSB to 0 then adds the result. Any carry will end up in the MSB of the result. The next bitmask isolates that carry. The final term checks for a set MSB on either x or y, which result in a carry overall. To meet the spec in the question, just do:
~(((x & 0x7FFFFFFF) + (y & 0x7FFFFFFF)) & 0x80000000 & (x | y)) >> 31
Let's suppose both numbers are unsigned integers. If you work with signed integers, it would be a little be more tricky as there is two ways to get overflow, either adding two large positives of adding two large negative. Anyway checking the most significant bits won't be enough, as addition propagates carry bit, you must take it into account.
For unsigned integers, if you don't care to cheat an easy way is:
(x+y < x) || (x+y < y)
This will work as most compilers won't do anything when overflow happen, just let it be.
You can also remarks that for overflow to happen at least one of the two numbers must have it's most significant bit set at 1. Hence something like that should work (beware, untested), but it's way more compilcated than the other version.
/* both Most Significant bits are 1 */
(x&y&0x80000000)
/* x MSb is 1 and carry propagate */
||((x&0x80000000)&&(((x&0x7FFFFFFF)+y)&0x80000000))
/* y MSb is 1 and carry propagate */
||((y&0x80000000)&&(((y&0x7FFFFFFF)+x)&0x80000000))
The logical ! is working fine for me.
me#desktop:~$ cat > so.c
#include <stdio.h>
void main() {
int y = 5;
int x = 3;
int t;
t = (((((x >> 31) + (y >> 31)) & 2) >> 1));
printf("%d\n", t);
t = !(((((x >> 31) + (y >> 31)) & 2) >> 1));
printf("%d\n", t);
}
^D
me#desktop:~$ gcc -o so so.c
me#desktop:~$ ./so
0
1
me#desktop:~$ uname -a
Linux desktop 2.6.32-23-generic #37-Ubuntu SMP Fri Jun 11 07:54:58 UTC 2010 i686 GNU/Linux
There is no simple bit-arithmetic-based test for overflow because addition involves carry. But there are simple tests for overflow that do not involve invoking overflow or unsigned integer wrapping, and they're even simpler than doing the addition then checking for overflow (which is of course undefined behavior for signed integers):
For unsigned integers x and y: (x<=UINT_MAX-y)
For signed integers, first check if they have opposite signs. If so, addition is automatically safe. If they're both positive, use (x<=INT_MAX-y). If they're both negative, use (x>=INT_MIN-y).
Are those signed integers by any chance? Your logic looks like it should be fine for unsigned integers (unsigned int) but not for regular ints, since in that case the shift will preserve the sign bit.