判断一个数是不是2的幂
我们经常会遇到这样一个问题,就是判断某个数据是否为2的n次方(1,2,4,8,16...)。例如如果用户输入的不是2^n,则要求用户重新输入。为了说明这种判断算法,我首先构造一个测试程序,代码如下:
#include <stdio.h>
#include <time.h>
int main()
{
long unsigned int i;
clock_t start,end;
start = clock();
for(i=1;i<100000000;i++)
{
if(is2Power(i))
{
printf("%ldn",i);
}
}
end =clock();
printf("The total time is: %lf",((double)(end-start))/CLOCKS_PER_SEC);
return 0;
}
一般人很容易想到下面的算法:
int is2Power(long unsigned int num)
{
long unsigned int i;
for(i=1;i<=num;i*=2)
{
if(i == num)
{
return 1;
}
}
return 0;
}
该算法很容易理解,但是效率不算特别高,在我的机器上的测试结果为:The total time is: 28.566000,有人提出,其中的i*=2,可以用i<<=1来替换,效率应该会高一些,我们可以尝试一下:
int is2Power(long unsigned int num)
{
long unsigned int i;
for(i=1;i<=num;i<<=1)
{
if(i == num)
{
return 1;
}
}
return 0;
}
在我的机器上的测试结果为:The total time is: 27.821000,我们发现仅仅提高了不到一秒,基本可以忽略不计。又有人提出,我们可以采取另一种思路,让i从num开始每次除2来判断,如果余数不为0立即返回,这样能会快判断出那些不符合条件的值,这样便能加快判断速度。
int is2Power(long unsigned int num)
{
long unsigned int i;
for(i=num;i>=1;i/=2)
{
if(i==1)
return 1;
else if(i%2 != 0)
{
return 0;
}
}
return 1;
}
这种算法在我的机器上的测试结果为:The total time is: 3.958000,可以看出效率提高了近8倍。这时又有大神提出,由于2的n次方的数二进制表示是第1位为1,其余为0,而x-1(假如x为2的n次方)得到的数的二进制表示恰恰是第1位为0,其余为1,两者相与,得到的结果就为0,否则结果肯定不为0。于是诞生了如下算法:
int is2Power(long unsigned int num)
{
return ((num & (num-1))==0)?1:0;
}
简单的有点吓人,而且效率也很高,在我的机器上的测试结果为:The total time is: 1.484000,当然也有一个类似的算法,原理类似:
int is2Power(long unsigned int num)
{
return ((num & (~num+1))==num)?1:0;
}
这种算法在我的机器上的测试结果为:The total time is: 1.503000
很简单的问题,只要我们仔细研究一下还是有不少收获的。
注:文中的算法仅说明了相对的效率问题,鲁棒性并没有测试,如果你在实际情况中使用,需要注意一下边界值和反常输入情况。
- 《Android外部存储》
- Android JNI出坑指南
- 《iPhone X ARKit Face Tracking》
- 结合标签广告,定制一个QQ邮箱订阅
- SecureCRT全局发送相同命令,快速抓取服务器信息的方法
- [不定期更新]简单的shell脚本练习实例
- 超简单的MySQL主从复制配置步骤
- 解决Centos下vsftp无法上传文件的问题,附vsftp配置详解
- 为iFrame添加动态载入效果,提高用户体验
- 分享超炫的表白页面和爱的纪念日源码
- 分享WordPress Mobile Pack汉化精简版及隐藏指定插件更新提示的方法
- Tomcat重启脚本For Windows
- js获取url中?后的参数,修复移动版无法切换到电脑版的BUG
- nginx配置文件参数详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ggplot2|玩转Manhattan图-你有被要求这么画吗?
- deconstructSigs|探寻cosmic的独特“气质”-mutation signature !
- barplot3d|圣诞节送你一个mutation signature搭建的“乐高”
- R读取gmt文件
- 一个画双层pie图的函数
- DEapp(差异表达分析)本地版——自由飞翔
- 盘一盘Tidyverse| 筛行选列之select,玩转列操作
- 2-14 |“特殊”的日子,多学一种表达爱的方式
- 盘一盘Tidyverse| 只要你要只要我有-filter 筛选行
- RNA相互作用神器——ENCORI
- R|tableone 快速绘制文章“表一”-基线特征三线表
- R-apply| 基因表达量批量二分类,Get!(修正版)
- TCGAbiolinks获取癌症临床信息
- R-rbind.fill|列数不一致的多个数据集“智能”合并,Get!
- R-ggpmisc|回归曲线添加回归方程,R2,方差表,香不香?