Skip to content

Instantly share code, notes, and snippets.

@jianminchen
Created May 25, 2016 18:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jianminchen/410d19acf623a7e2a4a349ccd8767c1e to your computer and use it in GitHub Desktop.
Save jianminchen/410d19acf623a7e2a4a349ccd8767c1e to your computer and use it in GitHub Desktop.
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