今天我需要一个简单的算法来检查数字是否是2的幂。

算法需要是:

  1. 简单
  2. 纠正任何ulong值。

我想出了这个简单的算法:

private bool IsPowerOfTwo(ulong number)
{if (number == 0)return false;for (ulong power = 1; power > 0; power = power << 1){// This for loop used shifting for powers of 2, meaning// that the value will become 0 after the last shift// (from binary 1000...0000 to 0000...0000) then, the 'for'// loop will break out.if (power == number)return true;if (power > number)return false;}return false;
}

但后来我想,如果检查log 2 x是否正好是一个圆数呢? 但是当我检查2 ^ 63 + 1时,由于四舍五入, Math.Log正好返回63。 所以我检查了功率63的2是否等于原始数字 - 它是,因为计算是用double s进行的,而不是精确的数字:

private bool IsPowerOfTwo_2(ulong number)
{double log = Math.Log(number, 2);double pow = Math.Pow(2, Math.Round(log));return pow == number;
}

对于给定的错误值,返回true9223372036854775809

有更好的算法吗?


#1楼

return (i & -i) == i


#2楼

private static bool IsPowerOfTwo(ulong x)
{var l = Math.Log(x, 2);return (l == Math.Floor(l));
}

#3楼

int isPowerOfTwo(unsigned int x)
{return ((x != 0) && ((x & (~x + 1)) == x));
}

这真的很快。 检查所有2 ^ 32个整数大约需要6分43秒。


#4楼

return ((x != 0) && !(x & (x - 1)));

如果x是2的幂,则它的1位处于位置n 。 这意味着x – 1位置为n 。 要了解原因,请回想一下二元减法是如何工作的。 当从x减去1时,借位一直传播到位置n ; 位n变为0,所有低位变为1.现在,由于xx – 1没有共同的1位, x & (x – 1)为0,并且!(x & (x – 1))为真。


#5楼

这是我设计的另一种方法,在这种情况下使用| 而不是&

bool is_power_of_2(ulong x) {if(x ==  (1 << (sizeof(ulong)*8 -1) ) return true;return (x > 0) && (x<<1 == (x|(x-1)) +1));
}

#6楼

bool IsPowerOfTwo(ulong x)
{return x > 0 && (x & (x - 1)) == 0;
}

#7楼

    bool IsPowerOfTwo(int n){if (n > 1){while (n%2 == 0){n >>= 1;}}return n == 1;}

这是一个通用算法,用于查明数字是否是另一个数字的幂。

    bool IsPowerOf(int n,int b){if (n > 1){while (n % b == 0){n /= b;}}return n == 1;}

#8楼

查找给定数字是否为2的幂。

#include <math.h>int main(void)
{int n,logval,powval;printf("Enter a number to find whether it is s power of 2\n");scanf("%d",&n);logval=log(n)/log(2);powval=pow(2,logval);if(powval==n)printf("The number is a power of 2");elseprintf("The number is not a power of 2");getch();return 0;
}

#9楼

0000 0001    Yes
0001 0001    No

算法

  1. 使用位掩码,将NUM除以二进制变量

  2. IF R > 0 AND L > 0: Return FALSE

  3. 否则, NUM变为非零值

  4. IF NUM = 1: Return TRUE

  5. 否则,请转到步骤1

复杂

时间~ O(log(d))其中d是二进制数字的数量


#10楼

接受的答案的以下附录可能对某些人有用:

当以二进制表示时,2的幂将总是看起来像1,然后是n个零 ,其中n大于或等于0. Ex:

Decimal  Binary
1        1     (1 followed by 0 zero)
2        10    (1 followed by 1 zero)
4        100   (1 followed by 2 zeroes)
8        1000  (1 followed by 3 zeroes)
.        .
.        .
.        .

等等。

当我们从这些数字中减去1 ,它们变为0,然后是n,并且n再次与上面相同。 例如:

Decimal    Binary
1 - 1 = 0  0    (0 followed by 0 one)
2 - 1 = 1  01   (0 followed by 1 one)
4 - 1 = 3  011  (0 followed by 2 ones)
8 - 1 = 7  0111 (0 followed by 3 ones)
.          .
.          .
.          .

等等。

来到了症结所在

当我们对数字x进行按位运算时会发生什么,这是2的幂, x - 1

的一个x被用的零对准x - 1和的全部零x与那些得到对准x - 1 ,导致位与导致0。这就是我们如何有上述被提及的单行答案对。


进一步增加上面接受的答案之美 -

所以,我们现在拥有一处房产:

当我们从任何数字中减去1时,那么在二进制表示中,最右边的1将变为0,而最右边的1之前的所有零将变为1

这个属性的一个很棒的用法是找出 - 给定数字的二进制表示中有多少1? 对于给定的整数x ,执行此操作的简短代码是:

byte count = 0;
for ( ; x != 0; x &= (x - 1)) count++;
Console.Write("Total ones in the binary representation of x = {0}", count);

可以从上面解释的概念证明的数字的另一个方面是“每个正数可以表示为2的幂的总和吗?”

是的,每个正数都可以表示为2的幂的总和。对于任何数字,取其二进制表示。 例如:拿号码117

The binary representation of 117 is 1110101Because  1110101 = 1000000 + 100000 + 10000 + 0000 + 100 + 00 + 1
we have  117     = 64      + 32     + 16    + 0    + 4   + 0  + 1

#11楼

这是一个简单的C ++解决方案:

bool IsPowerOfTwo( unsigned int i )
{return std::bitset<32>(i).count() == 1;
}

#12楼

bool isPow2 = ((x & ~(x-1))==x)? !!x : 0;

#13楼

对于任何2的幂,以下也适用。

N'( - N)==Ñ

注意:n = 0失败,因此需要检查它
这有效的原因是:
-n是n的2s补码。 与n相比,-n将n翻转的最右设置位左侧的每一位都设置为n。 对于2的幂,只有一个设置位。


#14楼

改进@ user134548的答案,无需位运算:

public static bool IsPowerOfTwo(ulong n)
{if (n % 2 != 0) return false;  // is odd (can't be power of 2)double exp = Math.Log(n, 2);if (exp != Math.Floor(exp)) return false;  // if exp is not integer, n can't be powerreturn Math.Pow(2, exp) == n;
}

这适用于:

IsPowerOfTwo(9223372036854775809)

#15楼

如果number是2的幂,则java中的该程序返回“true”,如果不是2的幂,则返回“false”

// To check if the given number is power of 2import java.util.Scanner;public class PowerOfTwo {int n;void solve() {while(true) {
//          To eleminate the odd numbersif((n%2)!= 0){System.out.println("false");break;}
//  Tracing the number back till 2n = n/2;
//  2/2 gives one so condition should be 1if(n == 1) {System.out.println("true");break;}}}public static void main(String[] args) {// TODO Auto-generated method stubScanner in = new Scanner(System.in);PowerOfTwo obj = new PowerOfTwo();obj.n = in.nextInt();obj.solve();}}OUTPUT :
34
false16
true

#16楼

return i> 0 &&(i ^ -i)==( - i << 1);

还没有找到这样的答案。 让它成为我的


#17楼

这个问题有一个简单的技巧:

bool IsPowerOfTwo(ulong x)
{return (x & (x - 1)) == 0;
}

注意,此函数将为0报告true ,这不是2的幂。 如果你想排除它,这是如何:

bool IsPowerOfTwo(ulong x)
{return (x != 0) && ((x & (x - 1)) == 0);
}

说明

首先是来自MSDN定义的按位二进制和运算符:

二进制和运算符是为整数类型和bool预定义的。 对于整数类型,&计算其操作数的逻辑按位AND。 对于bool操作数,&计算其操作数的逻辑AND; 也就是说,当且仅当它的两个操作数都为真时,结果才为真。

现在让我们来看看这一切是如何发挥作用的:

该函数返回boolean(true / false)并接受一个unsigned long类型的传入参数(在本例中为x)。 让我们为了简单起见假设某人已经传递了值4并且调用了这样的函数:

bool b = IsPowerOfTwo(4)

现在我们将每次出现的x替换为4:

return (4 != 0) && ((4 & (4-1)) == 0);

好吧,我们已经知道4!= 0 evals to true,到目前为止一直很好。 但是关于:

((4 & (4-1)) == 0)

这当然转化为:

((4 & 3) == 0)

但究竟什么是4&3

4的二进制表示为100,3的二进制表示为011(记住&取这些数字的二进制表示)。 所以我们有:

100 = 4
011 = 3

想象一下,这些价值就像基本的加法一样堆积起来。 &运算符表示如果两个值都等于1,则结果为1,否则为0. So 1 & 1 = 1 1 & 0 = 0 0 & 0 = 0 0 & 1 = 0 。 所以我们做数学:

100
011
----
000

结果只是0.所以我们回过头来看看我们的返回语句现在转换为:

return (4 != 0) && ((4 & 3) == 0);

现在翻译为:

return true && (0 == 0);
return true && true;

我们都知道true && truetrue ,这表明对于我们的例子,4是2的幂。


#18楼

发布问题后,我想到了以下解决方案:

我们需要检查一个二进制数字是否只有一个。 所以我们一次只将数字右移一位,如果等于1则返回true 。如果在任何时候我们得到一个奇数( (number & 1) == 1 ),我们知道结果是false 。 这证明(使用基准)比(大)真值的原始方法略快,对于假值或小值更快。

private static bool IsPowerOfTwo(ulong number)
{while (number != 0){if (number == 1)return true;if ((number & 1) == 1)// number is an odd number and not 1 - so it's not a power of two.return false;number = number >> 1;}return false;
}

当然,Greg的解决方案要好得多。


#19楼

一些记录和解释这个以及其他一些杂乱黑客的网站是:

  • http://graphics.stanford.edu/~seander/bithacks.html
    ( http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 )
  • http://bits.stephan-brumme.com/
    ( http://bits.stephan-brumme.com/isPowerOfTwo.html )

还有他们的祖父,小亨利·沃伦(Henry Warren,Jr。)写的“黑客的喜悦”一书 :

  • http://www.hackersdelight.org/

正如Sean Anderson的页面所解释的那样,表达式((x & (x - 1)) == 0)错误地表明0是2的幂。他建议使用:

(!(x & (x - 1)) && x)

纠正这个问题。


#20楼

我最近在http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/上写了一篇关于此的文章。 它包括位计数,如何正确使用对数,经典的“x &&!(x&(x - 1))”检查等。


#21楼

如果数字仅包含1个设置位,则数字为2的幂。 我们可以使用此属性和泛型函数countSetBits来查找数字是否为2的幂。

这是一个C ++程序:

int countSetBits(int n)
{int c = 0;while(n){c += 1;n  = n & (n-1);}return c;
}bool isPowerOfTwo(int n)
{        return (countSetBits(n)==1);
}
int main()
{int i, val[] = {0,1,2,3,4,5,15,16,22,32,38,64,70};for(i=0; i<sizeof(val)/sizeof(val[0]); i++)printf("Num:%d\tSet Bits:%d\t is power of two: %d\n",val[i], countSetBits(val[i]), isPowerOfTwo(val[i]));return 0;
}

我们不需要明确检查0是2的幂,因为它也返回False为0。

OUTPUT

Num:0   Set Bits:0   is power of two: 0
Num:1   Set Bits:1   is power of two: 1
Num:2   Set Bits:1   is power of two: 1
Num:3   Set Bits:2   is power of two: 0
Num:4   Set Bits:1   is power of two: 1
Num:5   Set Bits:2   is power of two: 0
Num:15  Set Bits:4   is power of two: 0
Num:16  Set Bits:1   is power of two: 1
Num:22  Set Bits:3   is power of two: 0
Num:32  Set Bits:1   is power of two: 1
Num:38  Set Bits:3   is power of two: 0
Num:64  Set Bits:1   is power of two: 1
Num:70  Set Bits:3   is power of two: 0

#22楼

bool isPowerOfTwo(int x_)
{register int bitpos, bitpos2;asm ("bsrl %1,%0": "+r" (bitpos):"rm" (x_));asm ("bsfl %1,%0": "+r" (bitpos2):"rm" (x_));return bitpos > 0 && bitpos == bitpos2;
}

如何检查数字是否为2的幂相关推荐

  1. C++检查数字是否为2的幂的实现算法(附完整源码)

    C++检查数字是否为2的幂的实现算法 C++检查数字是否为2的幂的实现算法完整源码(定义,实现,main函数测试) C++检查数字是否为2的幂的实现算法完整源码(定义,实现,main函数测试) #in ...

  2. C++检查给定数字是否为4的幂的算法实现(附完整源码)

    C++检查给定数字是否为4的幂的算法实现 C++检查给定数字是否为4的幂的算法实现完整源码(定义,实现,main函数测试) C++检查给定数字是否为4的幂的算法实现完整源码(定义,实现,main函数测 ...

  3. 如何在 Flutter 和 Dart 中检查数字字符串

    如何在 Flutter 和 Dart 中检查数字字符串 数字字符串只是字符串格式的数字. 数字字符串示例: '123', '0.123', '4.234,345', '-33.33', '+44.44 ...

  4. c语言程序负数,C程序,检查数字是正数还是负数

    C程序,检查数字是正数还是负数 在此示例中,您将学习检查数字(由用户输入)是负数还是正数. 要理解此示例,您应该了解以下C语言编程主题: 该程序从用户那里获取一个数字,并检查该数字是正数还是负数或零. ...

  5. 如何使用JavaScript检查数字是否为素数?

    素数是数论中最基础而最重要的概念.如果一个大于2的正整数,除了1和它本身之外,不是任何数的倍数,那么它就是一个素数.那么如何使用JavaScript检查数字是否为素数?下面本篇文章就来给大家介绍一下使 ...

  6. 数字迷阵(矩阵快速幂+结论题)

    数字迷阵(矩阵快速幂+结论题) 题目描述 小可可参观科学博物馆时,看到一件藏品,上面有密密麻麻的数字,如下所示:    1   2   3   5    8    13   21   34   55 ...

  7. 如何在 JavaScript 中检查数字是正数还是负数

    如何在 JavaScript 中检查数字是正数还是负数 前几天一个月薪35k的兄弟,给我推了一个人工智能学习网站,看了一段时间挺有意思的.包括语音识别.机器翻译等从基础到实战都有,很详细,分享给大家. ...

  8. 数字拆分为斐波那契数列_检查数字是否为斐波那契

    数字拆分为斐波那契数列 Description: 描述: We are often used to generate Fibonacci numbers. But in this article, w ...

  9. LeetCode 1922. 统计好数字的数目(快速幂)

    文章目录 1. 题目 2. 解题 1. 题目 我们称一个数字字符串是 好数字 当它满足(下标从 0 开始)偶数 下标处的数字为 偶数 且 奇数 下标处的数字为 质数 (2,3,5 或 7). 比方说, ...

最新文章

  1. 人大计算机在职考研好考吗,人大在职研究生好考吗?通过率高吗?
  2. java volatile修饰引用_关于volatile修饰引用类型的疑惑
  3. 【转载保存】接口压力测试安装与使用
  4. CS0656 缺少编译器要求的成员“Microsoft.CSharp..........
  5. JAVA 字符串驻留池
  6. poj2513Colored Sticks(无向图判欧拉路、回路+trie树)
  7. POJ 1005 I Think I Need a Houseboat
  8. Windows 7 驱动开发
  9. excel工作表保护如何无密码撤销
  10. 亲测好用的Topaz AI图像降噪软件:DeNoise AI mac版(支持m1)
  11. 怎么把笔记本的数据转移到台式机上?
  12. Dell服务器如何做raid
  13. 网易2019年春招笔试:爬塔玩法
  14. pocketsphinx 模型库_pocketSphinx 嵌入式关键词唤醒
  15. fortran matlab eng,[转载]关于MATLAB转FORTRAN的几点注意
  16. 揭秘Angular 2
  17. GaussDB架构(上)
  18. 解决Cannot call sendError() after the response has been committed和getOutputStream() has already been
  19. rust开发环境_Rust开发环境搭建
  20. 关于大学生早餐情况的调研报告

热门文章

  1. Educational Codeforces Round 12 B. Shopping 暴力
  2. MultipleRegularExpressionAttribute MVC中扩展自定义验证规则
  3. Binary XML file line #27: Error inflating class Listview
  4. CentOS安装之后的系统安全配置
  5. 九度 1529:棋盘寻宝(递推DP)
  6. FOSRestBundle功能包:视图层
  7. Set static ip for ubuntu
  8. 网络学习(一)网络版块主题介绍
  9. 机器学习项目实战----泰坦尼克号获救预测(一)
  10. 设计模式学习01策略模式记录