判断一个数是不是是 4 的整数次幂

Posted

技术标签:

【中文标题】判断一个数是不是是 4 的整数次幂【英文标题】:evaluate whether a number is integer power of 4判断一个数是否是 4 的整数次幂 【发布时间】:2010-08-09 02:00:46 【问题描述】:

声称下面的函数是用来判断一个数是否是4的整数次幂。我不太明白它是怎么工作的?

bool fn(unsigned int x)

if ( x == 0 ) return false;
if ( x & (x - 1) ) return false;
return x & 0x55555555;

【问题讨论】:

x & (x - 1) 删除数字的最低 1 位。 【参考方案1】:

第一个条件排除了 0,这显然不是 4 的幂,但会错误地通过以下两个测试。 (编辑:不,它不会,正如所指出的那样。第一个测试是多余的。)

下一个是一个不错的技巧:当且仅当数字是 2 的幂时,它才返回 true。2 的幂的特征是只设置一个位。设置了一位的数字减一会导致该数字之前的所有位都被设置(即 0x1000 减一为 0x0111)。和这两个数字,你得到 0。在任何其他情况下(即不是 2 的幂),至少会有一位重叠。

所以在这一点上,我们知道它是 2 的幂。

x & 0x55555555 如果设置了任何偶数位(位 0、位 2、位 4、位 6 等),则返回非零 (=true)。这意味着它是 4 的幂。(即 2 次未通过,但 4 次通过,8 次未通过,16 次通过等)。

【讨论】:

最后一次检查不会使第一次检查变得多余吗?据我所知,0 & 0x555555550 好点。更不用说它真的应该是 0 & 0x55555554(见我的编辑)。 1 怎么会出错?它不是 0,所以它会跳过第一个 if。当与 0 相加时,它是 0,所以它会跳过第二个 if。第三行和-s 设置了 1 位的东西,所以它返回 true。由于 1 = 4^0,它应该返回 true。对吗?【参考方案2】:

每个 4 的幂必须是 1 后跟偶数个零的形式(二进制表示):100...00

100 = 4

10000 = 16

1000000 = 64

    第一个测试(“if”)很明显。

    当从 XY100...00 形式的数字中减去 1 时,您会得到 XY011...11。因此,第二个测试检查数字中是否有多个“1”位(本例中为 XY)。

    最后一个测试检查这个“1”是否在正确的位置,即位 #2、4、6 等。如果不是,掩码 (&) 将返回非零结果。

【讨论】:

【参考方案3】:

以下解决方案适用于 2、4、16 次检查。

  public static boolean isPowerOf(int a, int b)
           
     while(b!=0 && (a^b)!=0)
                   
        b = b << 1;     
     
   return (b!=0)?true:false;   
  

isPowerOf(4,2) > true
isPowerOf(8,2) > true
isPowerOf(8,3) > false
isPowerOf(16,4) > true

【讨论】:

【参考方案4】:
var isPowerOfFour = function (n) 
let x = Math.log(n) / Math.log(4)
if (Number.isInteger(x)) 
    return true;
   
else 
    return false
   
;

isPowerOfFour(4) ->true
isPowerOfFour(1) ->true
isPowerOfFour(5) ->false

【讨论】:

这不能回答所提出的问题。 具体来说,OP 要求解释如何代码的工作原理,而不是相同功能的替代公式。

以上是关于判断一个数是不是是 4 的整数次幂的主要内容,如果未能解决你的问题,请参考以下文章

如何判断一个正整数是不是2的整数次幂

如何利用一条简单语句判断一个整数是否为2的整数次幂

判断一个正整数是否是2的整数次幂

2的整数次幂

快速判断一个数是否是4的幂次方,若是,并判断出来是多少次方!

2的整数次幂 面试算法