如何判断一个数是4的整数次幂

来源:互联网 发布:q系列plc编程基础篇 编辑:程序博客网 时间:2024/05/12 04:38
 

 转:http://topic.csdn.net/u/20090206/11/cc51806d-6d52-484a-9133-d29bb38dfe36.html

看是不是2的幂次方以及个位数是不是4 或6

bool fn(unsigned int x){  return (!( x & (x - 1) ) && (x % 10 == 4) || (x %10 == 6) ) ) || (x == 1);}

思路二下面有解释:

bool fn(unsigned int x){  if ( x == 0 ) return false;  if ( x & (x - 1) ) return false;  return x & 0x55555555;}


在上面判断2的幂次方的基础上我们对它进行拓展。
下面我来对这个问题进行数学归纳:
首先引入一个概念:幂掩码
幂掩码是,数值计算在计算机中的重要方法,它是判断数值处于那种以2为基的扩展幂次方。

4的幂次方的数一定是2的幂次方,但2的幂次方不一定是4的幂次方
设:数a=z^n那么2的幂次方的集合为:
A={a=2^n | n∈Z*}
那么满足4的幂次方呢:
B={a=4^n | n∈Z*}
=> B ={a=2^(2n) | n∈Z*}
令k = 2n,由于n∈Z* 
=>B={a=2^k | k∈Z* 且 k/2 = 0}

于是我们回到计算机,我们来说明下它们的关系
2进制表示 :10 ,100,1000, 10000, 100000, 1000000,它们都是2的幂次方应为它们显然满足结合A
上面红字部分表示的是4的幂次方,我们知道它们后面有2的公倍数个0,满足k,因此它们不但满足集合A也同样满足集合B。
那就是1后面的0是偶数个!
那么我们就int型数而言 和上面的数 和 0101 0101 0101 0101 0101 0101 0101 0101 (0xffffffff)进行按位与运算会如何?
如果 a∈A 并且 a&0xffffffff  为 1,那说明a∈B
下面我们来判断 8 的幂次方,由上述结论我们知道,2和4的幂次方分别满足以下:
A={a=2^n | n∈Z*}
B={a=4^n | n∈Z*}
那么8的幂次方:
C = {a=8^n | n∈Z*}
因为我们要把它转变为2的幂次方的描述,同理得:
C = {a=2^(3n) | n∈Z*}
令j = 2n,由于n∈Z*
=>C={a=2^j | j∈Z* 且 j/3 = 0}
同样有上面的规律我们得到
1000 1000000 1000000000 都是8的幂次方,0的个数是3的公倍数,满足j,
我们还就int型数而言,讨论它 0100 1001 0010 0100 1001 0010 0100 1001(0x69266926) 其实用8进制更好看更容易发现规律(01111111111) 01 001 001 001 001 001 001 001 001 001 001
以此类推我们得出16 32 的幂次方的规律是
16幂次方 0001 0001 0001 0001 0001 0001 0001 0001 (0x11111111)
32幂次方 0100 0010 0001 0000 1000 0100 0010 0001(0x62108621) (和8进制一样我们假定有32进制)(0r开头)实际上它是0r1111111(32进制)
好的我重温一下前面的4的幂次方,它的幂掩码是0xffffffff,其实我们引入4进制后(0h开头)实际上也是
0h1111111111111111(4进制)

下面是这些代码的实现,程序可以直接考到您机器上验证,注意网站有&符号的BUG 复制好注意字符:

#include <stdio.h>#define IS_POWER2(int_num)\  ((int_num) ? (((int_num) & (int_num) - 1) ? 0 : 1): 0)#define IS_POWER4(int_num)\  ((int_num) ? (((int_num) & (int_num) - 1) ? 0 : (((int_num)&0xffffffff) ? 1 : 0)): 0)#define IS_POWER8(int_num)\  ((int_num) ? (((int_num) & (int_num) - 1) ? 0 : (((int_num)&01111111111/*0x69266926*/) ? 1 : 0)): 0)#define IS_POWER16(int_num)\  ((int_num) ? (((int_num) & (int_num) - 1) ? 0 : (((int_num)&0x11111111) ? 1 : 0)): 0)#define IS_POWER32(int_num)\  ((int_num) ? (((int_num) & (int_num) - 1) ? 0 : (((int_num)&0x62108621) ? 1 : 0)): 0)int main(int ac, char **av){  int int_num;  int_num = atoi(av[1]);  if (IS_POWER2(int_num))  printf("%d is 2 power\n", int_num);  if (IS_POWER4(int_num))  printf("%d is 4 power\n", int_num);  if (IS_POWER8(int_num))  printf("%d is 8 power\n", int_num);  if (IS_POWER16(int_num))  printf("%d is 16 power\n", int_num);  if (IS_POWER32(int_num))  printf("%d is 32 power\n", int_num);  return 0;}