在写代码时遇到了“判断一个正整数是否是2的N次方”的问题,不想调用 java.lang 的 Math 类库进行浮点运算,觉得转换为浮点不是个好办法。

遂在网上搜索了一下,发现有人列出来好几种写法,列举几种:

1、通过循环除2;这种方法不值一提,略过;

2、针对32位/64位只有有限个 2 的N次方的常量值,逐个进行比较;额。。。这个也略过;

3、通过正则表达式进行文本匹配,判断是否2的后面都是 0 ;这个绕得更远了。。。

最后,有一种最简洁优雅的写法:(value & (value -1)) == 0;

喔,的确是简洁优雅!!!

不过,等等,接下来有人提出,似乎“所有2的N次方的结果都符合这个表达式”这点很容易证明;

可是如何证明符合条件“(value & (value -1)) == 0”的一定就是 2 的 N 次方呢?(N 是整数且大于等于0)。

想了一下,证明也不难,遂在此记下:

1、首先,记 A = value; B = value - 1;

2、既然 A & B == 0,那么意味着,A和B的二进制形式中,每一位都不相同;(例外的情况只有“两者都是 0” ,否则存在相同位的两个数的按位相与的结果不可能为 0)

3、由于 B = A - 1,即  A > B;基于第2点,A 和 B 每一位都不同,则可以推断出只有两种情况:

  (1)以二进制形式, A 最高位 1 与 B 的最高位 1 的位数相差 1 ;(x表示后面跟随的位数是 0 位到多位)

     A: 10xxxxxxx  
     B: 01xxxxxxx

  (2)第二种情况就是:A = 1,B = 0;

  显然第二种情况是符合命题的,因为 N = 0 ,2 的 N 次方的结果为 1 ; 接下来继续针对第一种情况做推导。

4、由于 A 与 B 仅相差1,那意味着在 B 的二进制的末尾加上 1 ,将会连续地向高位产生进位,最终导致 B 的最高位 01 进位为 10 ;

  注意,二进制形式中,能够“连续向高位产生进位”的情况只有一种,即 xxxxxxx 全部都是 1 ,也就是说 B 的全部是 1 ;

  由此,基于第2点,A 和 B 的每一位都不同,那么 A 除了最高位 1 之外,所有低位都是 0 ;

由此证得命题!

判断一个正整数是否是2的N次方的简洁算法及其证明的更多相关文章

  1. 判断一个整数是否是2的n次方

    参考:http://bbs.csdn.net/topics/370058619 如题,如何判断一个整数是否是2的N次方,我能想到的方法有两个 1.一直除2,看最后是否等于1.(最笨的方法) 2.转换成 ...

  2. 『转载』判断一个正整数是不是素数,时间复杂度为O(根号n)

    原文链接:https://blog.csdn.net/liangdagongjue/article/details/77895170#commentsedit PS:新手上路,实在找不到怎么转载,所以 ...

  3. 009 Palindrome Number 判断一个正整数是否是回文数

    详见:https://leetcode.com/problems/palindrome-number/description/ 实现语言:Java 方法一: class Solution { publ ...

  4. 几种判断一个整数是否是2的n次方幂的方法

    1:简单除法  int i = 128: //待判断的整数  int count = 1: //待判断的整数是2的count次方while (i){if (2 == i){printf("Y ...

  5. C语言:判断t所指字符串中的字母是否由连续递增字母组成。-判断一个输入的任何整数n,是否等于某个连续正整数序列之和。-将一副扑克牌编号为1到54,以某种方式洗牌,这种方式是将这副牌分成两半,然后将他们交叉,并始终保持编号1的牌在最上方。

    //判断t所指字符串中的字母是否由连续递增字母组成. #include <stdio.h> #include <string.h> void NONO(); int fun( ...

  6. 【C语言】输入一个正整数,判断其是否为素数

    素数的定义: 素数(prime number)又称质数,有无限个. 素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为素数.代码1: #include<stdio.h& ...

  7. 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。

    题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解法一:暴力求解.从1开始查找M,然后判断M*N=X这个数字是否只含有0,1. 解法二:由 ...

  8. Js判断一个字符串是否包含一个子串

    Js中经常遇到判断一个字符串是否包含一个子串,java语言中有containes的方法,直接调用就可以了.除非引用第三方数据库,Js中没有contains方法. 为了实现更java语言中contain ...

  9. python 判断一个字符串是否是小数

    """练习判断一个小数1.判断是否合法2.合法需要有一个小数点3.小数点左边必须是个整数,右边必须是个正整数 """ def xiaoshu ...

随机推荐

  1. PyQt环境配置

    1.下载python 登录Python官网,目前最新的版本是3.6.3,网址为:https://www.python.org/downloads/release/python-363/ 选中Windo ...

  2. symfony 命令

    1.创建Bundle php bin/console generate:bundle --namespace=Home/IndexBundle --format=yml  创建bundle会更新app ...

  3. python中注释的写法

    说明: 记录在python中注释的写法. 1.单行注释,代码行以 # 开头 # 这是一个单行注释 print('hello world') 2.多行注释,使用三个单引号,或者三个双引号将其要注释的内容 ...

  4. [原]unity3d调用android webView

    1.配置dialog xml文件: <resources>    <style name="dialogStyleWindow" parent="@an ...

  5. 8 -- 深入使用Spring -- 1...4 属性占位符配置器

    8.1.4 属性占位符配置器 PropertyPlaceholderConfigurer 是一个容器后处理器,负责读取Properties属性文件里的属性值,并将这些属性值设置成Spring配置文件的 ...

  6. iOS NSURLSession VS NSURLConnection

    NSURLSession VS NSURLConnection NSURLSession可以看做是NSURLConnection的进化版,其对NSURLConnection的改进点有: * 根据每个S ...

  7. Explaining Delegates in C# - Part 4 (Asynchronous Callback - Way 1)

    So far, I have discussed about Callback, Multicast delegates, Events using delegates, and yet anothe ...

  8. java serialize 浅谈

    对象的串行化(Serialization) 一.串行化的概念和目的 1.什么是串行化 对象的寿命通常随着生成该对象的程序的终止而终止.有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复.我们把 ...

  9. [PyCharm] 设置自动启动时自动打开项目

    设置启动PyCharm时自动打开(或不打开)上次进行的项目: 选择 “Settings - General - Reopen last project on startup”,勾选该选项则启动时自动打 ...

  10. gradle 两种更新方法

    第一种.Android studio更新 第一步:在你所在项目文件夹下:你项目根目录gradlewrappergradle-wrapper.properties 替换 distributionUrl= ...