热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

如何判定一个数是否为2的N次方

给定一个整数num,判断这个整数是否是2的N次方。比如,2,4,8是2的那次方,6,10不是2的N次方。因此我觉得,最保险的还是位运算,看多少个1,来的最实在。当然这里存在一个负数的问题。第一位是1,剩下全是0的问题。不过有一位聪明的回复者提供了一个很强大的方法来避开负数的用例:他给参数定的类型是uint!

题目:给定一个整数num,判断这个整数是否是2的N次方。比如,2,4,8是2的那次方,6,10不是2的N次方。

请看下面的程序:

public static bool Check1(int num)
{
    int i = 1;
    while (true)
    {
        if (i > num)
            return false;
        if (i == num)
            return true;
        i = i * 2;
    }
}

不断的循环num%2,如果不等于0,return false,如果等于0,num=num/2,一直做到num=1

public static bool Check2(int num)
{
    if (num == 1)
        return true;
    else
    {
        do
        {
            if (num % 2 == 0)
                num = num / 2;
            else
                return false;
        }
        while (num != 1);
        return true;
    }
}

其实这两种算法的思路都是相同的,但是第二种相对第一种更高效写,因为如果不是2的N次方,可以少循环很多次!

由于2的N次方的数二进制表示是第1位为1,其余为0,而x-1(假如x为2的N次方)得到的数的二进制表示恰恰是第1位为0,其余为1,两者相与,得到的结果就为0,否则结果肯定不为0。

public static boolean getResult(int num) 
{ 
	if (num <= 1) 
    { 
		return false; 
	} 
    else 
    { 
		return ((num & (num - 1)) == 0) ? true : false; 
	} 
} 
public static void main(String[] args) { 
	System.out.println(getResult(32)); 
} 

上面的程序多判断了一个1. 我们知道, 1是2的0次方。 1应该是符合要求的。下面修正:

	public static bool floor_7(int num)
    {
        if (num <= 1)
        {
            return false;
        }
        else
        {
            return ((num & (num - 1)) == 0) ? true : false;
        }
    }

如果一个数是2的整数次幂,那么表示为二进制的时候会是这样:010000....

除了2的零次方,即1之外,这个数减一会得到:001111....

换言之得到一个前面全是0后面全是1的数,把这个数和原数做个按位与,得到:000000.....

换言之,如果一个数n,其不为1,且n-1 & n = 0,那么n就是一个2的整数次幂。因为只要他表达为二进制时存在两个1,就不会满足这条规律。所以最简判断方法就是:

if ( n <0 )
throw new InvalidOperationException();
if ( n <2 )
return false;
return n & ( n - 1 ) == 0

修正之后:

	public bool floor_8(int n)
    {
        if (n <0)
            throw new InvalidOperationException();
        if (n <2)
            return false;
        return n & (n - 1) == 0;
    }

对数算法:

bool foo(int x)
{
    float ret = log(x)/log(2); 
    return abs((int) ret - ret) <= 0.00001;
}

修正后:

	public bool floor_22(int x)
    {
        float ret = log(x) / log(2);
        return abs((int)ret - ret) <= 0.00001;
    }

对数算法比较有趣, 可惜, 浮点误差毕竟不是个容易避开的问题。因为浮点数不能直接比较, 所以用了一个0.00001来做尺度。这就存在了一个问题:当x很大的时候呢?我找了一个变态的数字来测试:0x10000001

结果是true。因为结果的小数部分实在是太小了。

static void Main(string[] args)
{
	int i = int.Parse(Console.ReadLine());
	Console.WriteLine(IsCheck(i));
}
public static bool IsCheck(int num)
{
	double result = Math.Log(num, 2);
	if (result.ToString().IndexOf(".") >= 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

相同的问题。 只要使用了LOG, 就无法避免掉浮点数丢精度的问题。 这是没办法的事情。

	public static bool floor_37(int num)
    {
        double result = Math.Log(num, 2);
        if (result.ToString().IndexOf(".") >= 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

所以总结了下, (x)&(x-1)的算法还没有被证明, 不知道除了0还有没有别的反例。因为毕竟这个算式没有严密的证明过程。

因此我觉得, 最保险的还是位运算, 看多少个1, 来的最实在。当然这里存在一个负数的问题。第一位是1, 剩下全是0的问题。 不过有一位聪明的回复者提供了一个很强大的方法来避开负数的用例:他给参数定的类型是uint!

好吧你赢了。

本文地址:http://www.nowamagic.net/librarys/veda/detail/1031,欢迎访问原出处。


推荐阅读
  • 使用TabActivity实现Android顶部选项卡功能
    本文介绍如何通过继承TabActivity来创建Android应用中的顶部选项卡。通过简单的步骤,您可以轻松地添加多个选项卡,并实现基本的界面切换功能。 ... [详细]
  • 软件测试行业深度解析:迈向高薪的必经之路
    本文深入探讨了软件测试行业的发展现状及未来趋势,旨在帮助有志于在该领域取得高薪的技术人员明确职业方向和发展路径。 ... [详细]
  • Go从入门到精通系列视频之go编程语言密码学哈希算法(二) ... [详细]
  • 为助力科研人员提升数据处理与图形展示能力,活动家携手北京市计算中心推出2017年R语言数据可视化研讨会。详情及注册信息请点击链接查看。 ... [详细]
  • 本文详细介绍了在 Ubuntu 16.04 系统上安装和配置 PostgreSQL 数据库的方法,包括如何设置监听地址、启用密码加密、更改默认用户密码以及调整客户端访问控制。 ... [详细]
  • 在OpenCV 3.1.0中实现SIFT与SURF特征检测
    本文介绍如何在OpenCV 3.1.0版本中通过Python 2.7环境使用SIFT和SURF算法进行图像特征点检测。由于这些高级功能在OpenCV 3.0.0及更高版本中被移至额外的contrib模块,因此需要特别处理才能正常使用。 ... [详细]
  • 张正友相机标定算法解析:无需棋盘格
    本文深入探讨了张正友教授于1998年提出的单平面标定技术,该方法结合了传统标定与自标定的优势,通过简易的棋盘格实现了高效准确的相机标定。 ... [详细]
  • 使用 MATLAB 将高光谱数据集转换为伪彩色 CIE 图像
    本文介绍了一种方法,通过 MATLAB 将高光谱数据集的每个维度的图像转换为伪彩色 CIE 图像。用户只需指定波段即可完成转换。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • Windows操作系统提供了Encrypting File System (EFS)作为内置的数据加密工具,特别适用于对NTFS分区上的文件和文件夹进行加密处理。本文将详细介绍如何使用EFS加密文件夹,以及加密过程中的注意事项。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • 菜鸟物流用户增长部现正大规模招聘P6及以上级别的JAVA工程师,提供年后入职选项。 ... [详细]
  • 深入解析层次聚类算法
    本文详细介绍了层次聚类算法的基本原理,包括其通过构建层次结构来分类样本的特点,以及自底向上(凝聚)和自顶向下(分裂)两种主要的聚类策略。文章还探讨了不同距离度量方法对聚类效果的影响,并提供了具体的参数设置指导。 ... [详细]
  • QQ推出新功能:个性化QID身份卡
    您是否还记得曾经风靡一时的即时通讯工具QQ?近日,QQ悄然上线了一项新功能——QID身份卡。这项功能将如何改变用户的社交体验?本文为您详细解读。 ... [详细]
  • 本文详细介绍了如何在ARM架构的目标设备上部署SSH服务端,包括必要的软件包下载、交叉编译过程以及最终的服务配置与测试。适合嵌入式开发人员和系统集成工程师参考。 ... [详细]
author-avatar
沉稳之固_300
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有