在写代码时遇到了“判断一个正整数是否是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. servlet3.0 新特性和springboot Listener和filter案例

    1.filter package com.newtouch.zxf.filter; import java.io.IOException; import javax.servlet.Filter; i ...

  2. nginx反向代理配置(nginx.conf+proxy_set_header)

    转载:https://blog.csdn.net/bjsunwei/article/details/62231209 location / { proxy_pass http://test; prox ...

  3. GreenPlum数据库安装

    第一章    文档概述 本文描述适用于Greenplum4.0以上版本的安装操作.所涉及到的操作系统相关参数调整,主要针对Redhat Linux操作系统. 第二章    安装介质 操作系统:Cent ...

  4. scala中list集合的操作与总结

    /** * Created by root * Description : List */ object ListTest { def main(args: Array[String]): Unit ...

  5. java的对象锁和类锁

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  6. sql 替换字符串

    MSSQL替换语句: )),'abc.com','123.com') 例如: update PE_Article set Content=replace(cast(Content as varchar ...

  7. Nginx(十)-- 进程模型及工作原理

    1.nginx进程模型 Nginx是一个master和worker的模型.master主要用来管理worker进程,master就比作老板,worker就是打工仔,master指挥worker来做事情 ...

  8. 《转载》Tomcat内存设置详解

    原文地址:Java内存溢出详解 一.常见的Java内存溢出有以下三种: 1. java.lang.OutOfMemoryError: Java heap space ----JVM Heap(堆)溢出 ...

  9. Jquery 网页转换为图片

    /* html2canvas 0.5.0-alpha1 <http://html2canvas.hertzen.com> Copyright (c) 2015 Niklas von Her ...

  10. 对Android 开发者有益的 40 条优化建议(转)

    下面是开始Android编程的好方法: 找一些与你想做事情类似的代码 调整它,尝试让它做你像做的事情 经历问题 使用StackOverflow解决问题 对每个你像添加的特征重复上述过程.这种方法能够激 ...