Created
May 25, 2016 18:05
-
-
Save jianminchen/410d19acf623a7e2a4a349ccd8767c1e to your computer and use it in GitHub Desktop.
Power of 2 solutions - 10 solutions - based on blog: http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace PowerOfTwo | |
{ | |
/* | |
* May 25, 2016 | |
* | |
* source code from: | |
* http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/ | |
*/ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
bool result1 = isPowerOfTwo_CountOne(3); | |
bool result2 = isPowerOfTwo_ShiftRight(7); | |
bool result3 = isPowerOfTwo_DecrementAndCompare(7); | |
bool result4 = isPowerOfTwo_DecrementAndCompare(32); | |
bool result5 = isPowerOfTwo_ComplementAndCompare(32); | |
} | |
// 1. Divide by two | |
// C++ unsigned int analog in C#: | |
// http://stackoverflow.com/questions/18851705/c-sharp-equivalent-of-64-bit-unsigned-long-long-in-c | |
public bool isPowerOfTwo_DivideByTwo (ulong x) | |
{ | |
while (((x % 2) == 0) && x > 1) /* While x is even and > 1 */ | |
x /= 2; | |
return (x == 1); | |
} | |
// 2. check all | |
public static bool isPowerOfTwo_checkAll (ulong x) | |
{ | |
return ( | |
x == 1 || x == 2 || x == 4 || x == 8 || x == 16 || x == 32 || | |
x == 64 || x == 128 || x == 256 || x == 512 || x == 1024 || | |
x == 2048 || x == 4096 || x == 8192 || x == 16384 || | |
x == 32768 || x == 65536 || x == 131072 || x == 262144 || | |
x == 524288 || x == 1048576 || x == 2097152 || | |
x == 4194304 || x == 8388608 || x == 16777216 || | |
x == 33554432 || x == 67108864 || x == 134217728 || | |
x == 268435456 || x == 536870912 || x == 1073741824 || | |
x == 2147483648); | |
} | |
// 3. check next power | |
public static bool isPowerOfTwo_CheckNextPower (ulong x) | |
{ | |
ulong powerOfTwo = 1; | |
while (powerOfTwo < x && powerOfTwo < 2147483648) | |
powerOfTwo *= 2; | |
return (x == powerOfTwo); | |
} | |
// 4. Linear Search | |
public static bool isPowerOfTwo_LinearSearch (ulong x) | |
{ | |
ulong[] powersOfTwo = new ulong[32] | |
{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768, | |
65536,131072,262144,524288,1048576,2097152,4194304,8388608, | |
16777216,33554432,67108864,134217728,268435456,536870912, | |
1073741824,2147483648}; | |
int exponent = 0; | |
while (powersOfTwo[exponent] < x && exponent < 31) | |
exponent++; | |
return (x == powersOfTwo[exponent]); | |
} | |
// 5. Binary Search | |
public static bool isPowerOfTwo_BinarySearch (ulong x) | |
{ | |
ulong[] powersOfTwo = new ulong[32] | |
{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768, | |
65536,131072,262144,524288,1048576,2097152,4194304,8388608, | |
16777216,33554432,67108864,134217728,268435456,536870912, | |
1073741824,2147483648}; | |
bool isAPowerOfTwo; | |
int interval = 16; | |
int exponent = interval; /* Start out at midpoint */ | |
switch (x) { | |
case 0: | |
isAPowerOfTwo = false; | |
break; | |
case 1: /* Special case makes binary search easier */ | |
isAPowerOfTwo = true; | |
break; | |
default: | |
while (x != powersOfTwo[exponent] && interval > 1) { | |
if (x < powersOfTwo[exponent]) | |
exponent -= interval/2; | |
else | |
exponent += interval/2; | |
interval /= 2; | |
} | |
isAPowerOfTwo = x == powersOfTwo[exponent]; | |
break; | |
} | |
return (isAPowerOfTwo); | |
} | |
// 6. Log Search | |
public static bool isPowerOfTwo_LogSearch (ulong x) | |
{ | |
int exponent = 0; | |
bool isAPowerOfTwo; | |
ulong[] powersOfTwo = new ulong[32] | |
{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768, | |
65536,131072,262144,524288,1048576,2097152,4194304,8388608, | |
16777216,33554432,67108864,134217728,268435456,536870912, | |
1073741824,2147483648}; | |
if (x == 0 || x > 2147483648) | |
isAPowerOfTwo = false; | |
else | |
{ | |
exponent = (int)(Math.Log((double)x)/Math.Log(2.0)); /* Log base 2 */ | |
isAPowerOfTwo = (x == powersOfTwo[exponent] || | |
x == powersOfTwo[exponent+1]); | |
} | |
return (isAPowerOfTwo); | |
} | |
// 7. Count ones | |
public static bool isPowerOfTwo_CountOne (ulong x) | |
{ | |
ulong numberOfOneBits = 0; | |
while(x > 0 && numberOfOneBits <= 1) | |
{ | |
if ((x & 1) == 1) /* Is the least significant bit a 1? */ | |
numberOfOneBits++; | |
x >>= 1; /* Shift number one bit to the right */ | |
} | |
return (numberOfOneBits == 1); /* 'True' if only one 1 bit */ | |
} | |
// 8. Shift Right | |
/* | |
This function is the equivalent of the Divide by Two algorithm. | |
Dividing a binary integer by 2 is the same as shifting it right one bit, | |
and checking whether a binary integer is odd is the same as checking if | |
its least significant bit is 1. | |
* */ | |
public static bool isPowerOfTwo_ShiftRight (ulong x) | |
{ | |
while (((x & 1) == 0) && x > 1) /* While x is even and > 1 */ | |
x >>= 1; | |
return (x == 1); | |
} | |
// 9. Decrement and Compare | |
/* | |
* There are two halves to the expression: x != 0 and !(x & (x – 1)). | |
* The first half makes 0 a special case, since the second half only | |
* works correctly for positive numbers. The second half — the interesting part | |
* of the expression — is true when x is a power of two and false when x is | |
* not. | |
* Let’s see why. | |
Let n be the position of the leftmost 1 bit if x. If x is a power of two, | |
* its lone 1 bit is in position n. This means x – 1 has a 0 in position n. | |
* To see why, recall how binary subtraction works. When subtracting 1 from x, | |
* the borrow propagates all the way to position n; bit n becomes 0 and all | |
* lower bits become 1. Now, since x has no 1 bits in common with x – 1, | |
* x & (x – 1) is 0, and !(x & (x – 1)) is true. | |
Here are some examples (I’ll use 8-bit unsigned integers to keep | |
* things manageable): | |
* Decrement and Compare, when x is a power of two | |
* | |
x x – 1 x & (x – 1) | |
00000001 00000000 00000000 | |
00000100 00000011 00000000 | |
00010000 00001111 00000000 | |
* | |
*/ | |
public static bool isPowerOfTwo_DecrementAndCompare (ulong x) | |
{ | |
return ((x != 0) && ((x & (x - 1)) == 0)); | |
} | |
// 10. Complement and Compare | |
/* | |
* The first half of the expression ensures that x is a positive integer. | |
* The second half of the expression, (x & (~x + 1)) == x, is true only | |
* when x is a power of two. It compares x with its two’s complement. | |
* The two’s complement of x is computed with ~x + 1, which inverts the | |
* bits of x and adds 1 (~x + 1 is equivalent to -x, but negation is | |
* technically illegal for an unsigned integer). | |
* | |
* Let n be the position of the leftmost 1 bit if x. If x is a power of two, | |
* its lone 1 bit is in position n. This means ~x has a 0 in position n and | |
* 1s everywhere else. When 1 is added to ~x, all positions below n become 0 | |
* and the 0 at position n becomes 1. In other words, the carry propagates | |
* all the way to position n. So what happens is this: negating x inverts | |
* all its bits, but adding 1 inverts them back, from position n on down. | |
* So, (x & (~x + 1)) == x is true. | |
* | |
* If x is not a power of two, ~x has at least one 0 below position n. | |
* When 1 is added, the carry will not propagate to position n. In other words, | |
* not all bits from position n and below will be inverted back. This means | |
* (x & (~x + 1)) == x is false. | |
*/ | |
public static bool isPowerOfTwo_ComplementAndCompare(ulong x) | |
{ | |
return ((x != 0) && ((x & (~x + 1)) == x)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment