如何计算比给定数字大的2的幂数

news/2024/9/19 15:58:52/文章来源:https://www.cnblogs.com/leecoder5/p/18420739

举例

比如3,计算后得出4,比如6,计算后得出8,

这种根据人类最直观的想法,当然一下能看出来,因为我们会去估计大于这个数字的2^n方是多少,但是数字大了就不是人类该做的事情了

如果根据最简单的思维,从2的0次方开始,增加n值,一个个循环试过去,也可以找到这个值,但是效率显然很低,我从源码里找到了两种高效的计算方式:

第一种计算方法

   int tableSizeFor(int source) {int maxCapacity = 1 << 30;int n = source- 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;return (n < 0) ? 1 : (n >= maxCapacity ) ? maxCapacity : n + 1;}

接下来分析一下这个过程:
假设所求数字source = 20,那么n = 19

n=19
0000 0000 0000 0000 0000 0000 0001 0011
n>>>1
0000 0000 0000 0000 0000 0000 0000 1001
n |= n >>> 1
0000 0000 0000 0000 0000 0000 0001 1011
n>>>2
0000 0000 0000 0000 0000 0000 0000 0110
n |= n >>> 2
0000 0000 0000 0000 0000 0000 0001 1111
n>>>4
0000 0000 0000 0000 0000 0000 0000 0001
n |= n >>> 4
0000 0000 0000 0000 0000 0000 0001 1111
n>>>8
0000 0000 0000 0000 0000 0000 0000 0000
n |= n >>> 8
0000 0000 0000 0000 0000 0000 0001 1111
n>>>16
0000 0000 0000 0000 0000 0000 0000 0000
n |= n >>> 16
0000 0000 0000 0000 0000 0000 0001 1111
(n < 0) ? 1 : (n >= maxCapacity ) ? maxCapacity : n + 1
0000 0000 0000 0000 0000 0000 0010 0000

最后算出的结果就是32,过程很清晰了,那这是一个什么原理呢,其实就是通过位移31次(1+2+4+8+16)以及或运算,把当前最高位下面的二进制都填满1,这样再加1以后就能得到比原先高一位的数字,这个算法不可谓不高明。不知道有没有同学能认出来这个算法是出自于哪一段源码的呢?

第二种计算方法

int tableSizeFor(int source) {int n = 1;if (source >>> 16 == 0) {n += 16;source <<= 16;}if (source >>> 24 == 0) {n += 8;source <<= 8;}if (source >>> 28 == 0) {n += 4;source <<= 4;}if (source >>> 30 == 0) {n += 2;source <<= 2;}n -= source >>> 31;return 1<<(32-n);
}

过程分析:
假设source = 20

source 
0000 0000 0000 0000 0000 0000 0001 0100右移16位 等于0 --> n+=16=17
0000 0000 0000 0000 0000 0000 0000 0000左移16位 source当前值
0000 0000 0001 0100 0000 0000 0000 0000右移24位 等于0 --> n+=8=25
0000 0000 0000 0000 0000 0000 0000 0000左移8位 source当前值
0001 0100 0000 0000 0000 0000 0000 0000右移28位 不等于0 --> n和source都不变
0000 0000 0000 0000 0000 0000 0000 0001右移30位 等于0 --> n+=2=27
0000 0000 0000 0000 0000 0000 0000 0000左移2位 source当前值
0101 0000 0000 0000 0000 0000 0000 0000source右移31位,等于0
0101 0000 0000 0000 0000 0000 0000 0000n -= source >>> 31

最后得出n=27,1<<(32-n)=32,这个算法比较繁冗一点,理解起来也稍微困难些,这个算法的目的在于先求出当前数字的左边高位有多少个0,然后用32减去这个0的数量就是所需要的幂了。
这当中求0的数量的过程是个重点,也是通过位移来实现,先向右位移16次,如果等于0了,那说明前面16个高位都是0,n可以加16,如果不等于0,可以继续往下走,最后总归能让你等于0,这样计算累加下去就可以求出前面0的数量。
上面那段源码我没改方法名,可能有人能猜出代码的出处,那这段代码谁能猜到出自哪段源码呢?

源码出处

  • 第一段代码是HashMap里求threshold的过程,方法名就叫tableSizeFor
  • 第二段代码是出自Integer类的numberOfLeadingZeros方法,目的就是求出当前数字的左边高位有多少个0。这个方法调用的地方很多,ForkJoinPool,BigInteger,ConcurrentHashMap等等

单从求高一阶幂数这点来说,第一种算法更精妙一点,第二种略显笨拙,但是第二种算法也很好,用处也多。不管怎么说,位移始终是最贴近计算机的操作,是最快速的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/799915.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

易优eyoucms网站无法安装,数据库文件版本号(无)与CMS源码版本号(v1.3.1)不一致,点击查看!

解决方法比较简单, 可以找历史版本, 使用同版本数据库或者源码进行安装, 安装完成后操作升级。扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟悉各种CMS,精通PHP+MYSQL、HTML5、CSS3、Javascript等。承接:企业仿站、网站修改、网站改版、BUG修复、问题处…

易优eyoucms网站添加自定义新建字段的时候报错

根据提供的错误信息 SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large. The maximum row size for the used table type not counting BLOBs is 65535. You have to change some columns to TEXT or BLOBs,这个错误表明数据库表的行大小超过了 My…

易优eyoucms网站下载的系统导入就数据库出问题了,如何升级数据库?

数据库版本需要一样 数据库有新建模型的 需要打补丁包再导入扫码添加技术【解决问题】专注中小企业网站建设、网站安全12年。熟悉各种CMS,精通PHP+MYSQL、HTML5、CSS3、Javascript等。承接:企业仿站、网站修改、网站改版、BUG修复、问题处理、二次开发、PSD转HTML、网站被黑、…

易优eyoucms网站登录报错:Array and string offset access syntax with curly braces is deprecated

根据提供的错误信息 Array and string offset access syntax with curly braces is deprecated,这个错误提示表明当前使用的 PHP 版本不支持使用大括号 {} 来访问数组和字符串偏移量。这种语法在 PHP 7.4 之后被标记为已弃用。 以下是一些可能的解决步骤: 1. 切换 PHP 版本 尝…

易优eyoucms网站报错,\\core\\library\\think\\db\\Connection.php

报错 \\\\core\\\\library\\\\think\\\\db\\\\Connection.php 第 380 行左右 数据表或视图不存在,请联系技术处理。[错误代码] SQLSTATE[42S02]: Base table or view not found: 1146 Table eyoucms.ey_channeltype doesnt exist 根据提供的错误信息 SQLSTATE[42S02]: Base ta…

高等数学 3.3 泰勒公式

泰勒(Taylor)中值定理1 如果函数 \(f(x)\) 在 \(x_0\) 处具有 \(n\) 阶导数,那么存在 \(x_0\) 的一个邻域,对于该领域内的任一 \(x\) ,有 \[f(x) = f(x_0) + f^{}(x_0)(x - x_0) + \cfrac{f^{}(x_0)}{2!}(x - x_0)^2 + \cdots + \cfrac{f^{(n)}(x_0)}{n!}(x - x_0)^n + R_…

腾讯云TDSQL数据库认证值得考吗?来看看TDSQL证书有什么用

国内市场上的数据库产品有不少,很多大企业都有自己的数据库产品,比如金仓的KingBase、华为的OpenGauss、阿里云的PolarDB、达梦DM数据库等等,腾讯云也有自己的数据库产品,叫做TDSQL数据库,TDSQL数据库有两个分支:基于MySQL版 + 基于PostgreSQL版。腾讯云是国内知名的云平…

Maximum execution time of 30 seconds exceeded

遇到 Maximum execution time of 30 seconds exceeded 这个错误,通常是因为 PHP 脚本执行时间超过了设定的最大执行时间限制。这可能是由于脚本执行了耗时的操作,例如长时间的数据库查询或其他资源密集型任务。 以下是一些解决步骤: 1. 增加最大执行时间限制 可以在 PHP 配置…

易优eyoucms网站报错 \core\library\think\db\Connection.php 第 307 行左右,SQLSTATE[HY000] [1045]访问被拒,这样的情况要怎么处理啊

根据提供的错误信息 SQLSTATE[HY000] [1045] Access denied for user cs2021@localhost (using password: YES),这个错误表明数据库访问被拒绝了,通常是因为用户名或密码不正确导致的。 以下是几个可能的解决步骤:检查数据库连接配置:确认数据库连接配置文件中的用户名和密…

如何用Python将HTTP接口封装成可视化页面。

在软件行业中,经常会遇到有一些功能只能通过接口触发,没有页面。这样很不方便,。 我们这里,就是通过PyQt5实现,将接口的入参,封装成一个可视化的表单。将用户在表单中填写的数据,传给接口,接口再带参请求业务1.先看最终的效果,用户打开桌面应用后,只会出现下面的弹窗…

易优eyoucms网站php5.4版本,报错:Cant use method return value in write context

当你在使用 PHP 5.4 版本时遇到 “Cant use method return value in write context” 的错误,这通常是因为你在代码中错误地使用了方法返回值。这种错误通常发生在试图将方法返回值直接赋值给变量或用于其他上下文时。 解决方案 以下是一些常见的原因和解决方法: 1. 检查代码…

易优eyoucms网站报错 /core/library/think/db/Connection.php 第 389 行左右,如何解决?

SQLSTATE[42S22]: Column not found: 1054 Unknown column groupid in where clause 遇到“SQLSTATE[42S22]: Column not found: 1054 Unknown column groupid in where clause”这类错误,通常是因为数据库表结构与代码中的查询不匹配。具体来说,可能是数据库表中缺少某个列(…