判断一个正整数是否是2的N次方的简洁算法及其证明
在写代码时遇到了“判断一个正整数是否是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次方的简洁算法及其证明的更多相关文章
- 判断一个整数是否是2的n次方
参考:http://bbs.csdn.net/topics/370058619 如题,如何判断一个整数是否是2的N次方,我能想到的方法有两个 1.一直除2,看最后是否等于1.(最笨的方法) 2.转换成 ...
- 『转载』判断一个正整数是不是素数,时间复杂度为O(根号n)
原文链接:https://blog.csdn.net/liangdagongjue/article/details/77895170#commentsedit PS:新手上路,实在找不到怎么转载,所以 ...
- 009 Palindrome Number 判断一个正整数是否是回文数
详见:https://leetcode.com/problems/palindrome-number/description/ 实现语言:Java 方法一: class Solution { publ ...
- 几种判断一个整数是否是2的n次方幂的方法
1:简单除法 int i = 128: //待判断的整数 int count = 1: //待判断的整数是2的count次方while (i){if (2 == i){printf("Y ...
- C语言:判断t所指字符串中的字母是否由连续递增字母组成。-判断一个输入的任何整数n,是否等于某个连续正整数序列之和。-将一副扑克牌编号为1到54,以某种方式洗牌,这种方式是将这副牌分成两半,然后将他们交叉,并始终保持编号1的牌在最上方。
//判断t所指字符串中的字母是否由连续递增字母组成. #include <stdio.h> #include <string.h> void NONO(); int fun( ...
- 【C语言】输入一个正整数,判断其是否为素数
素数的定义: 素数(prime number)又称质数,有无限个. 素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为素数.代码1: #include<stdio.h& ...
- 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。
题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解法一:暴力求解.从1开始查找M,然后判断M*N=X这个数字是否只含有0,1. 解法二:由 ...
- Js判断一个字符串是否包含一个子串
Js中经常遇到判断一个字符串是否包含一个子串,java语言中有containes的方法,直接调用就可以了.除非引用第三方数据库,Js中没有contains方法. 为了实现更java语言中contain ...
- python 判断一个字符串是否是小数
"""练习判断一个小数1.判断是否合法2.合法需要有一个小数点3.小数点左边必须是个整数,右边必须是个正整数 """ def xiaoshu ...
随机推荐
- python使用paramiko自动化部署linux程序
使用paramiko模块,比os模块和command模块更加的兼容各种环境.后面两个只能在服务器本机 执行,此模块写得python文件无论是在本地还是服务器本身上运行,都能兼容. paramiko模块 ...
- Present ViewController Modally (转)
一.主要用途 弹出模态ViewController是IOS变成中很有用的一个技术,UIKit提供的一些专门用于模态显示的ViewController,如UIImagePickerController等 ...
- MySQL------报错Access denied for user 'root'@'localhost' (using password:NO)解决方法
报错:Access denied for user 'root'@'localhost' (using password:NO) 原因:没有给用户“root'@'localhost”赋予数据库权限 解 ...
- MySQL---循环语句
mysql 操作同样有循环语句操作,网上说有3中标准的循环方式: while 循环 . loop 循环和repeat循环.还有一种非标准的循环: goto. 鉴于goto 语句的跳跃性会造成使用的的思 ...
- EhCache初体验
一.简介 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点.Ehcache是一种广泛使用的开源Java分布式缓存.主要面向通用缓存,Java EE和轻量级容器.它具有内存和磁盘存 ...
- [Python] Unofficial Windows Binaries for Python Extension Packages
1. Unofficial Windows Binaries for Python Extension Packages 非官方的Python第三方库,提供基于Windows的二进制扩展包,由加州大学 ...
- pojo与DTO的区别
ational Mapping(对象关系映射)的缩写.通俗点讲,就是将对象与关系数据库绑定,用对象来表示关系数据.在O/R Mapping的世界里,有两个基本的也是重要的东东需要了解,即VO,PO. ...
- 手把手让你实现开源企业级web高并发解决方案(lvs+heartbeat+varnish+nginx+eAccelerator+memcached)
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://freeze.blog.51cto.com/1846439/677348 此文凝聚 ...
- warning C4305:“初始化”:从“double”到“float”截断
编译VS项目时出现警告: warning C4305:“初始化”:从“double”到“float”截断(warning C4305: 'initializing' : truncation from ...
- 微信公众号access_token的获取与存储
如果是一个用户触发,那么只要将access_token放在数据库,文件,nosql就行,取时判断时间是否过期,过期重新去微信获取再放入. 如果是很多用户,多进程并发,特别是分布式那种架构呢?进程A判断 ...