|
|
1
65
这是我最喜欢的。除了最初检查它是否无效(<0,如果你知道你只会传入>=0个数字,你可以跳过它)外,它没有循环或条件,因此将优于大多数其他方法。这类似于埃里克森的答案,但我认为我在开头递减x并在结尾加1比他的答案稍微不那么尴尬(也避免了结尾的条件)。
答案在
Given an integer, how do I find the next largest power of two using bit-twiddling?
对这种常见算法的工作原理进行了一些解释,并给出了几个输入的位模式示例。(该版本使用
相同的dec/shift/OR/inc策略可在以下内容中找到:
|
|
|
2
19
|
|
|
3
12
在英特尔硬件上,BSR指令与您想要的非常接近-它会找到最重要的设置位。如果您需要更精确,那么您可能会想知道剩余的位是否正好为零。 我倾向于假设其他CPU会有类似BSR的东西——这是一个你想要回答的问题,以规范化一个数字。 如果你的数字超过32位,那么你会从最重要的DWORD进行扫描,找到第一个DWORD 任何 位设置。 Edsger Dijkstra可能会说,上述“算法”假设你的计算机使用二进制数字,而从他那种崇高的“算法”角度来看,你应该考虑图灵机或其他东西——显然我的风格更务实。 |
|
|
4
11
本着《雷神之锤II》的0x5f3759df和Bit Twidling Hacks的IEEE版本的精神,该解决方案采用双精度来提取指数作为计算下限(lg2(n))的手段。它比公认的解决方案快一点,也比bit Twidling IEEE版本快得多,因为它避免了浮点运算。按照编码,它假设double是小字节序机器上真正的*8 IEEE浮点数。
编辑:在同事的帮助下添加优化的x86程序集版本。速度提高了4%,但仍比bsr版本慢约50%(对于n=1..2^31-2,我的笔记本电脑为6秒对4秒)。
|
|
5
6
这是位移位技术的模板版本。
由于循环只使用常量,因此它会被编译器压平。(我检查了)该功能也是面向未来的。 这里有一个使用__builtin_clz的。(也是面向未来的)
|
|
|
6
6
你的实现并不幼稚,它实际上是合乎逻辑的,除了它是错误的——对于大于最大整数大小1/2的数字,它返回负数。 假设你可以将数字限制在0到2^30的范围内(对于32位整数),它会工作得很好,而且比任何涉及对数的数学函数都快得多。 无符号整数会更好,但你最终会得到一个无限循环(对于大于2^31的数字),因为<<操作员。 |
|
|
7
6
pow(2,ceil(log2(值)); log2(值)=log(值)/log(2); |
|
|
8
4
关于密切相关问题的可能解决方案(即四舍五入而不是向上)的探索,其中许多解决方案比简单方法快得多,请访问 Bit Twiddling Hacks 页面,一个很好的资源来做你正在寻找的优化。最快的解决方案是使用具有256个条目的查找表,这将总操作计数从朴素方法的平均62个(通过类似的操作计数方法)减少到大约7个。使这些解决方案适应你的问题只是一个比较和增量的问题。 |
|
|
9
3
你并没有真正说出你所说的“更好的算法”是什么意思,但由于你提出的算法非常清楚(如果有点缺陷),我假设你正在寻找一种更有效的算法。 Larry Gritz给出了可能是最有效的c/c++算法,没有查找表的开销,在大多数情况下就足够了(参见 http://www.hackersdelight.org 对于类似的算法)。 正如其他地方提到的,如今大多数CPU都有机器指令来计算前导零的数量(或等效地返回ms集位),但它们的使用是不可移植的,在大多数情况下不值得付出努力。 然而,大多数编译器都有“内在”功能,允许使用机器指令,但以更便携的方式。 Microsoft C++有_BitScanReverse(),gcc提供__builtin_clz()来高效地完成大部分工作。 |
|
|
10
3
使用递归模板版本生成编译常量怎么样:
可以这样使用:
|
|
|
11
1
在标准C++20中
仅
Beware that
例如,
对于2的补码系统上的负输入,这是正确的,除了
|
|
12
1
下面的代码反复剥离最低位,直到数字是2的幂,然后将结果加倍,除非数字一开始是2的乘幂。它的优点是在与设置的比特数成比例的时间内运行。不幸的是,它的缺点是在几乎所有情况下都需要比问题中的代码或程序集建议更多的指令。我把它包括在内只是为了完整。
|
|
|
13
1
我知道这是下投票诱饵,但如果数字足够小(比如8或16位),直接查找可能是最快的。
通过先执行高位字,然后执行低位字,可以将其扩展到32位。
这种转变或方法可能并不好,但也许可以扩展到更大的单词大小。 (实际上,这给出了最高的1位。你必须将其向左移动1才能得到下一个更高的2次幂。) |
|
|
14
0
我的版本是一样的:
|
|
|
15
0
我喜欢这种转变。 我会接受的
这样循环总是终止的,&&几乎从不进行评估。 我认为两行代码不值得调用函数。你也可以根据自己的判断做一个长的或短的,而且它非常易读。 (如果bufferPow变为负数,希望你的主代码能快速退出。) 通常你在算法开始时只计算一次2-power,所以优化无论如何都是愚蠢的。然而,如果有人足够无聊,会对速度竞赛感兴趣。..使用上述示例和255 256 257。. 4195 4196 4197 |
|
|
16
-2
通过除以2的对数,可以将任意的对数函数转换为对数基2:
当然,这不会是100%精确的,因为其中涉及浮点运算。 |
|
|
feasega · 聚合物模拟-2个节点之间的最短路线,适用于所有节点 1 年前 |
|
|
Alisa Petrova · 在有向图中更改一对顶点以创建循环 1 年前 |
|
|
b39b332d · 使用C++标准库实现高效间隔存储 1 年前 |
|
ABGR · 二叉树的直径——当最长路径不通过根时的失败案例 1 年前 |
|
|
EpicAshman · 数独棋盘程序中同一列和同一行出现两次的数字 1 年前 |