Bit manipulation for identity property - c

Given an integer and either 1 or 0, I'd like to be able to get either the integer or 0 using only bitwise operators. That means no if statements, conditionals, etc. Basically integer * i. Two's complement system!
I have been working for a while and it is tricky. Here are my failed attempts:
Edit: ints are unsigned
unsigned int x = 24; // To change
unsigned int i = 0; // identity
((~i) | x) // if i = 0, ~i returns 111...1 || (111...1 | x) = 111...1
// else ~i returns 000...1 || (000...1 | x) = x (+1 sometimes)
The code I have above makes it so if i is 1, then I get the identity (only sometimes), and if i is 0, then I get -1. I'd like it so if i is 1, I get the identity, and if i is 0, I get 0. Thanks!

I think this is what you want:
i & -x
If x is zero, you get i & 0 which is zero. If x is one, you get i & UINT_MAX which is i.

This can be done using
~i + 1u & x
~0u produces UINT_MAX (all bits 1):
1111...1111
Adding 1 goes back to 0:
0000...0000
On the other hand, ~1u produces UINT_MAX - 1:
1111...1110
Adding 1 then gives UINT_MAX (all bits 1):
1111...1111
These are perfect bit masks to use with &: (0 & x) == 0 and (UINT_MAX & x) == x.

Related

Problems about check a integer is zero or negative with only operator in C?

/*
* isPower2 - returns 1 if x is a power of 2, and 0 otherwise
* Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
* Note that no negative number is a power of 2.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 4
*/
int isPower2(int x) {
/*
* Variable a checks if x is power of 2, x and x - 1 won't have a 1
* in the same place if it's power of 2. Variable b checks if x is
* negative or zero. Use & to combine !a and b to complete the function.
*/
int a = x &(x+(~1+1));
int b = ((x+(~1+1))>> 31)+1;
return (!a)&b;
}
Hello every one, I am self-learning a course called CSE351 form Washton University and am finishing the lab1 about data manipulation in C. As you
can see about this question, I need to use the variable b to tell whether or not
the int x is zero.
And then I think that for zero or negative, if you minus one and then right shift 31 bits, adding one, you will get zero if the int is 0, and 1 if it is positive.
But however, my code didn't work, but I found a line of code works.
int b = ((!(x >> 31)) & (~(!x)));
I am really confused why my code don't work, can somebody tell me why?
Edit: Sorry, I didn't mention the environment of this lab is based on int with 32 bits and 2's complement for negative.
Several things to note (in your code):
first, (~1 + 1) is the same as ~0, and the same as -1 (in two's complement). Simpler, right?
x + (~0) is the same as x - 1. Simpler, right?
x & (x - 1) is 1 all the bits that don't change and are 1, when x is decremented. I think what you pretend here is to write x ^ (x - 1) that is, the set of bits that carry to the next on a decrement. This is the bits that change in a decrement. It happens that all bits change iff the number is a power of two. In case you want the bits that don't change, instead of using ^, just use & (bits that are 1 and don't change on a decrement which must be the empty set in case of a power of two ---we have to complement the result, as this boolean gives the opposite) This expression could be the result to get a power of two, if you consider the special case of 0 that is returned as a power of two. As with negatives, and 0, the logarithm does not exist, so we can simply say if (x <= 0) return 0; else return !(x & (x - 1)); (THIS CAN BE THE REQUESTED SOLUTION) or more compact return x <= 0 ? 0 : !(x&(x-1));.
~a as a consequence is _all the bits that do change OR are 0 when x is decremented. I'm lost completely here on what you pretend. I think you want to get if x <= 0 but that's so easy to write in C, instead of the complications you show.
So, your intentions (I guess) is to use the number of 1 bits that don't change on a decrement, because all bits do change for powers of two. Then, a possible implementation should be:
#include <stdio.h>
/*
* isPower2 - returns 1 if x is a power of 2, and 0 otherwise
* Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
* Note that no negative number is a power of 2. (and zero also, there's no logarithm of zero)
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 4
*/
int isPower2(int x) {
return x <= 0
? 0
: !(x&(x-1));
}
/* please, always post complete and verifiable code, with header files,
* and the like, so we can test it without having to first modify it.
*/
int main()
{
for (;;) {
int a;
scanf("%d", &a);
printf("isPower2(a=%d) => %d\n", a, isPower2(a));
}
}
NOTE
Anyway, I don't have a clear idea of the result you want to get, as you entitle the question as Problems about check a integer is zero or negative... and then you show partial code (see How to create a Minimal, Complete, and Verifiable example) about how to detect if some given integer is a power of two but then, you show then some strange code to check if a number is negative. It suffices to do:
if (x <= 0) do_bla_bla();
and this doesn't produce undefined behaviour with 31 bit right shifts.
NOTE
if you need to use only the operators in the list, just change <= by the following:
#define SIGNBIT (~(~0>>1)) /* ALL ONES, SHIFTED ONE BIT RIGHT AND COMPLEMENTED */
return
x & SIGNBIT /* sign bit on, negative number */
|| !x /* OR x == 0 */
? 0
: !(x&(x-1));
The final code is:
#include <stdio.h>
/*
* isPower2 - returns 1 if x is a power of 2, and 0 otherwise
* Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
* Note that no negative number is a power of 2. (and zero also, there's no logarithm of zero)
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 4
*/
#define SIGNBIT (~(~0>>1))
int isPower2(int x) {
return x & SIGNBIT || !x ? 0 : !(x&(x-1));
/* if anybody tells you are using ? and || operators, just write:
* if (x & SIGNBIT) return 0;
* if (!x) return 0;
* return !(x&(x-1));
*/
}
/* please, always post complete and verifiable code, with header files,
* and the like, so we can test it without having to first modify it.
*/
int main()
{
for (;;) {
int a;
scanf("%d", &a);
printf("isPower2(a=%d) => %d\n", a, isPower2(a));
}
}

simulate jg instruction(datalab's isGreater)

I am doing CSAPP's datalab, the isGreater function.
Here's the description
isGreater - if x > y then return 1, else return 0
Example: isGreater(4,5) = 0, isGreater(5,4) = 1
Legal ops: ! ~ & ^ | + << >>
Max ops: 24
Rating: 3
x and y are both int type.
So i consider to simulate the jg instruction to implement it.Here's my code
int isGreater(int x, int y)
{
int yComplement = ~y + 1;
int minusResult = x + yComplement; // 0xffffffff
int SF = (minusResult >> 31) & 0x1; // 1
int ZF = !minusResult; // 0
int xSign = (x >> 31) & 0x1; // 0
int ySign = (yComplement >> 31) & 0x1; // 1
int OF = !(xSign ^ ySign) & (xSign ^ SF); // 0
return !(OF ^ SF) & !ZF;
}
The jg instruction need SF == OF and ZF == 0.
But it can't pass a special case, that is, x = 0x7fffffff(INT_MAX), y = 0x80000000(INT_MIN).
I deduce it like this:
x + yComplement = 0xffffffff, so SF = 1, ZF = 0, since xSign != ySign, the OF is set to 0.
So, what's wrong with my code, is my OF setting operation wrong?
You're detecting overflow in the addition x + yComplement, rather than in the overall subtraction
-INT_MIN itself overflows in 2's complement; INT_MIN == -INT_MIN. This is the 2's complement anomaly1.
You should be getting fast-positive overflow detection for any negative number (other than INT_MIN) minus INT_MIN. The resulting addition will have signed overflow. e.g. -10 + INT_MIN overflows.
http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt has a table of input/output signs for add and subtraction. The cases that overflow are where the inputs signs are opposite but the result sign matches y.
SUBTRACTION SIGN BITS (for num1 - num2 = sum)
num1sign num2sign sumsign
---------------------------
0 0 0
0 0 1
0 1 0
*OVER* 0 1 1 (subtracting a negative is the same as adding a positive)
*OVER* 1 0 0 (subtracting a positive is the same as adding a negative)
1 0 1
1 1 0
1 1 1
You could use this directly with the original x and y, and only use yComplement as part of getting the minusResult. Adjust your logic to match this truth table.
Or you could use int ySign = (~y) >> 31; and leave the rest of your code unmodified. (Use a tmp to hold ~y so you only do the operation once, for this and yComplement). The one's complement inverse (~) does not suffer from the 2's complement anomaly.
Footnote 1: sign/magnitude and one's complement have two redundant ways to represent 0, instead of an value with no inverse.
Fun fact: if you make an integer absolute-value function, you should consider the result unsigned to avoid this problem. int can't represent the absolute value of INT_MIN.
Efficiency improvements:
If you use unsigned int, you don't need & 1 after a shift because logical shifts don't sign-extend. (And as a bonus, it would avoid C signed-overflow undefined behaviour in +: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html).
Then (if you used uint32_t, or sizeof(unsigned) * CHAR_BIT instead of 31) you'd have a safe and portable implementation of 2's complement comparison. (signed shift semantics for negative numbers are implementation-defined in C.) I think you're using C as a sort of pseudo-code for bit operations, and aren't interested in actually writing a portable implementation, and that's fine. The way you're doing things will work on normal compilers on normal CPUs.
Or you can use & 0x80000000 to leave the high bits in place (but then you'd have to left shift your ! result).
It's just the lab's restriction, you can't use unsigned or any constant larger than 0xff(255)
Ok, so you don't have access to logical right shift. Still, you need at most one &1. It's ok to work with numbers where all you care about is the low bit, but where the rest hold garbage.
You eventually do & !ZF, which is either &0 or &1. Thus, any high garbage in OF` is wiped away.
You can also delay the >> 31 until after XORing together two numbers.
This is a fun problem that I want to optimize myself:
// untested, 13 operations
int isGreater_optimized(int x, int y)
{
int not_y = ~y;
int minus_y = not_y + 1;
int sum = x + minus_y;
int x_vs_y = x ^ y; // high bit = 1 if they were opposite signs: OF is possible
int x_vs_sum = x ^ sum; // high bit = 1 if they were opposite signs: OF is possible
int OF = (x_vs_y & x_vs_sum) >> 31; // high bits hold garbage
int SF = sum >> 31;
int non_zero = !!sum; // 0 or 1
return (~(OF ^ SF)) & non_zero; // high garbage is nuked by `& 1`
}
Note the use of ~ instead of ! to invert a value that has high garbage.
It looks like there's still some redundancy in calculating OF separately from SF, but actually the XORing of sum twice doesn't cancel out. x ^ sum is an input for &, and we XOR with sum after that.
We can delay the shifts even later, though, and I found some more optimizations by avoiding an extra inversion. This is 11 operations
// replace 31 with sizeof(int) * CHAR_BIT if you want. #include <limit.h>
// or use int32_t
int isGreater_optimized2(int x, int y)
{
int not_y = ~y;
int minus_y = not_y + 1;
int sum = x + minus_y;
int SF = sum; // value in the high bit, rest are garbage
int x_vs_y = x ^ y; // high bit = 1 if they were opposite signs: OF is possible
int x_vs_sum = x ^ sum; // high bit = 1 if they were opposite signs: OF is possible
int OF = x_vs_y & x_vs_sum; // low bits hold garbage
int less = (OF ^ SF);
int ZF = !sum; // 0 or 1
int le = (less >> 31) & ZF; // clears high garbage
return !le; // jg == jnle
}
I wondered if any compilers might see through this manual compare and optimize it into cmp edi, esi/ setg al, but no such luck :/ I guess that's not a pattern that they look for, because code that could have been written as x > y tends to be written that way :P
But anyway, here's the x86 asm output from gcc and clang on the Godbolt compiler explorer.
Assuming two's complement, INT_MIN's absolute value isn't representable as an int. So, yComplement == y (ie. still negative), and ySign is 1 instead of the desired 0.
You could instead calculate the sign of y like this (changing as little as possible in your code) :
int ySign = !((y >> 31) & 0x1);
For a more detailed analysis, and a more optimal alternative, check Peter Cordes' answer.

Bitwise operation and masks

I am having problem understanding how this piece of code works. I understand when the x is a positive number, actually only (x & ~mark) have a value; but cannot figure what this piece of code is doing when x is a negative number.
e.g. If x is 1100(-4), and mask would be 0001, while ~mask is 1110.
The result of ((~x & mask) + (x & ~mask)) is 0001 + 1100 = 1011(-3), I tried hard but cannot figure out what this piece of code is doing, any suggestion is helpful.
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
/* mask the sign bit against ~x and vice versa to get highest bit in x. Shift by n-1, and not. */
int mask = x >> 31;
return !(((~x & mask) + (x & ~mask)) >> (n + ~0));
}
Note: this is pointless and only worth doing as an academic exercise.
The code makes the following assumptions (which are not guaranteed by the C standard):
int is 32-bit (1 sign bit followed by 31 value bits)
int is represented using 2's complement
Right-shifting a negative number does arithmetic shift, i.e. fill sign bit with 1
With these assumptions in place, x >> 31 will generate all-bits-0 for positive or zero numbers, and all-bits-1 for negative numbers.
So the effect of (~x & mask) + (x & ~mask) is the same as (x < 0) ? ~x : x .
Since we assumed 2's complement, ~x for negative numbers is -(x+1).
The effect of this is that if x is positive it remains unchanged. and if x is negative then it's mapped onto the range [0, INT_MAX] . In 2's complement there are exactly as many negative numbers as non-negative numbers, so this works.
Finally, we right-shift by n + ~0. In 2's complement, ~0 is -1, so this is n - 1. If we shift right by 4 bits for example, and we shifted all the bits off the end; it means that this number is representable with 1 sign bit and 4 value bits. So this shift tells us whether the number fits or not.
Putting all of that together, it is an arcane way of writing:
int x;
if ( x < 0 )
x = -(x+1);
// now x is non-negative
x >>= n - 1; // aka. x /= pow(2, n-1)
if ( x == 0 )
return it_fits;
else
return it_doesnt_fit;
Here is a stab at it, unfortunately it is hard to summarize bitwise logic easily. The general idea is to try to right shift x and see if it becomes 0 as !0 returns 1. If right shifting a positive number n-1 times results in 0, then that means n bits are enough to represent it.
The reason for what I call a and b below is due to negative numbers being allowed one extra value of representation by convention. An integer can represent some number of values, that number of values is an even number, one of the numbers required to represent is 0, and so what is left is an odd number of values to be distributed among negative and positive numbers. Negative numbers get to have that one extra value (by convention) which is where the abs(x)-1 comes into play.
Let me know if you have questions:
int fitsBits(int x, int n) {
int mask = x >> 31;
/* -------------------------------------------------
// A: Bitwise operator logic to get 0 or abs(x)-1
------------------------------------------------- */
// mask == 0x0 when x is positive, therefore a == 0
// mask == 0xffffffff when x is negative, therefore a == ~x
int a = (~x & mask);
printf("a = 0x%x\n", a);
/* -----------------------------------------------
// B: Bitwise operator logic to get abs(x) or 0
----------------------------------------------- */
// ~mask == 0xffffffff when x is positive, therefore b == x
// ~mask == 0x0 when x is negative, therefore b == 0
int b = (x & ~mask);
printf("b = 0x%x\n", b);
/* ----------------------------------------
// C: A + B is either abs(x) or abs(x)-1
---------------------------------------- */
// c is either:
// x if x is a positive number
// ~x if x is a negative number, which is the same as abs(x)-1
int c = (a + b);
printf("c = %d\n", c);
/* -------------------------------------------
// D: A ridiculous way to subtract 1 from n
------------------------------------------- */
// ~0 == 0xffffffff == -1
// n + (-1) == n-1
int d = (n + ~0);
printf("d = %d\n", d);
/* ----------------------------------------------------
// E: Either abs(x) or abs(x)-1 is shifted n-1 times
---------------------------------------------------- */
int e = (c >> d);
printf("e = %d\n", e);
// If e was right shifted into 0 then you know the number would have fit within n bits
return !e;
}
You should be performing those operations with unsigned int instead of int.
Some operations like >> will perform an arithmetic shift instead of logical shift when dealing with signed numbers and you will have this sort of unexpected outcome.
A right arithmetic shift of a binary number by 1. The empty position in the most significant bit is filled with a copy of the original MSB instead of zero. -- from Wikipedia
With unsigned int though this is what happens:
In a logical shift, zeros are shifted in to replace the discarded bits. Therefore the logical and arithmetic left-shifts are exactly the same.
However, as the logical right-shift inserts value 0 bits into the most significant bit, instead of copying the sign bit, it is ideal for unsigned binary numbers, while the arithmetic right-shift is ideal for signed two's complement binary numbers. -- from Wikipedia

Moving a "nibble" to the left using C

I've been working on this puzzle for awhile. I'm trying to figure out how to rotate 4 bits in a number (x) around to the left (with wrapping) by n where 0 <= n <= 31.. The code will look like:
moveNib(int x, int n){
//... some code here
}
The trick is that I can only use these operators:
~ & ^ | + << >>
and of them only a combination of 25. I also can not use If statements, loops, function calls. And I may only use type int.
An example would be moveNib(0x87654321,1) = 0x76543218.
My attempt: I have figured out how to use a mask to store the the bits and all but I can't figure out how to move by an arbitrary number. Any help would be appreciated thank you!
How about:
uint32_t moveNib(uint32_t x, int n) { return x<<(n<<2) | x>>((8-n)<<2); }
It uses <<2 to convert from nibbles to bits, and then shifts the bits by that much. To handle wraparound, we OR by a copy of the number which has been shifted by the opposite amount in the opposite direciton. For example, with x=0x87654321 and n=1, the left part is shifted 4 bits to the left and becomes 0x76543210, and the right part is shifted 28 bits to the right and becomes 0x00000008, and when ORed together, the result is 0x76543218, as requested.
Edit: If - really isn't allowed, then this will get the same result (assuming an architecture with two's complement integers) without using it:
uint32_t moveNib(uint32_t x, int n) { return x<<(n<<2) | x>>((9+~n)<<2); }
Edit2: OK. Since you aren't allowed to use anything but int, how about this, then?
int moveNib(int x, int n) { return (x&0xffffffff)<<(n<<2) | (x&0xffffffff)>>((9+~n)<<2); }
The logic is the same as before, but we force the calculation to use unsigned integers by ANDing with 0xffffffff. All this assumes 32 bit integers, though. Is there anything else I have missed now?
Edit3: Here's one more version, which should be a bit more portable:
int moveNib(int x, int n) { return ((x|0u)<<((n&7)<<2) | (x|0u)>>((9+~(n&7))<<2))&0xffffffff; }
It caps n as suggested by chux, and uses |0u to convert to unsigned in order to avoid the sign bit duplication you get with signed integers. This works because (from the standard):
Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
Since int and 0u have the same rank, but 0u is unsigned, then the result is unsigned, even though ORing with 0 otherwise would be a null operation.
It then truncates the result to the range of a 32-bit int so that the function will still work if ints have more bits than this (though the rotation will still be performed on the lowest 32 bits in that case. A 64-bit version would replace 7 by 15, 9 by 17 and truncate using 0xffffffffffffffff).
This solution uses 12 operators (11 if you skip the truncation, 10 if you store n&7 in a variable).
To see what happens in detail here, let's go through it for the example you gave: x=0x87654321, n=1. x|0u results in a the unsigned number 0x87654321u. (n&7)<<2=4, so we will shift 4 bits to the left, while ((9+~(n&7))<<2=28, so we will shift 28 bits to the right. So putting this together, we will compute 0x87654321u<<4 | 0x87654321u >> 28. For 32-bit integers, this is 0x76543210|0x8=0x76543218. But for 64-bit integers it is 0x876543210|0x8=0x876543218, so in that case we need to truncate to 32 bits, which is what the final &0xffffffff does. If the integers are shorter than 32 bits, then this won't work, but your example in the question had 32 bits, so I assume the integer types are at least that long.
As a small side-note: If you allow one operator which is not on the list, the sizeof operator, then we can make a version that works with all the bits of a longer int automatically. Inspired by Aki, we get (using 16 operators (remember, sizeof is an operator in C)):
int moveNib(int x, int n) {
int nbit = (n&((sizeof(int)<<1)+~0u))<<2;
return (x|0u)<<nbit | (x|0u)>>((sizeof(int)<<3)+1u+~nbit);
}
Without the additional restrictions, the typical rotate_left operation (by 0 < n < 32) is trivial.
uint32_t X = (x << 4*n) | (x >> 4*(8-n));
Since we are talking about rotations, n < 0 is not a problem. Rotation right by 1 is the same as rotation left by 7 units. Ie. nn=n & 7; and we are through.
int nn = (n & 7) << 2; // Remove the multiplication
uint32_t X = (x << nn) | (x >> (32-nn));
When nn == 0, x would be shifted by 32, which is undefined. This can be replaced simply with x >> 0, i.e. no rotation at all. (x << 0) | (x >> 0) == x.
Replacing the subtraction with addition: a - b = a + (~b+1) and simplifying:
int nn = (n & 7) << 2;
int mm = (33 + ~nn) & 31;
uint32_t X = (x << nn) | (x >> mm); // when nn=0, also mm=0
Now the only problem is in shifting a signed int x right, which would duplicate the sign bit. That should be cured by a mask: (x << nn) - 1
int nn = (n & 7) << 2;
int mm = (33 + ~nn) & 31;
int result = (x << nn) | ((x >> mm) & ((1 << nn) + ~0));
At this point we have used just 12 of the allowed operations -- next we can start to dig into the problem of sizeof(int)...
int nn = (n & (sizeof(int)-1)) << 2; // etc.

Tell if a 32 bit signed int is a power of 2

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.

Resources