先上核心代码(文末附针对多种整数类型的代码):

inline int log_2(int x) {
int rst = 0;
if (x & 0xffff'0000U) rst += 16, x >>= 16;
if (x & 0x0000'ff00U) rst += 8, x >>= 8;
if (x & 0x0000'00f0U) rst += 4, x >>= 4;
if (x & 0x0000'000cU) rst += 2, x >>= 2;
if (x & 0x0000'0002U) rst += 1 ;
return rst;
}

原理很简单:

首先,任意正整数都可以拆分为数个互不相等的 2 的幂的和,且这些 2 的幂都小于等于该数;

其次,int 占用 32 位,故对于 int 范围内的数,其对数都不超过 31

最后,容易注意到二进制与对数间的天然联系,介于这种联系是显然且不易描述的,在此不予点明[doge];

综上,对于 int 类型的数据,其对数必然可以通过 {16, 8, 4, 2, 1} 组合出来,通过其二进制位即可判断其对数是由那几个数组合的。


附录(以下代码效率差别可以忽略不计,但代码量有显著差距):

inline auto log_2(uint64_t x) { // also unsigned long long
uint64_t rst = 0;
if (x & 0xffff'ffff'0000'0000ULL) rst += 32, x >>= 32;
if (x & 0x0000'0000'ffff'0000ULL) rst += 16, x >>= 16;
if (x & 0x0000'0000'0000'ff00ULL) rst += 8, x >>= 8;
if (x & 0x0000'0000'0000'00f0ULL) rst += 4, x >>= 4;
if (x & 0x0000'0000'0000'000cULL) rst += 2, x >>= 2;
if (x & 0x0000'0000'0000'0002ULL) rst += 1 ;
return rst;
}
inline auto log_2(uint32_t x) { // also unsigned int
uint32_t rst = 0;
if (x & 0xffff'0000U) rst += 16, x >>= 16;
if (x & 0x0000'ff00U) rst += 8, x >>= 8;
if (x & 0x0000'00f0U) rst += 4, x >>= 4;
if (x & 0x0000'000cU) rst += 2, x >>= 2;
if (x & 0x0000'0002U) rst += 1 ;
return rst;
}
inline auto log_2(uint16_t x) { // also unsigned short
uint16_t rst = 0;
if (x & 0x0000'ff00U) rst += 8, x >>= 8;
if (x & 0x0000'00f0U) rst += 4, x >>= 4;
if (x & 0x0000'000cU) rst += 2, x >>= 2;
if (x & 0x0000'0002U) rst += 1 ;
return rst;
}
inline auto log_2(uint8_t x) { // also unsigned char
uint8_t rst = 0;
if (x & 0x00f0U) rst += 4, x >>= 4;
if (x & 0x000cU) rst += 2, x >>= 2;
if (x & 0x0002U) rst += 1 ;
return rst;
}

快速 log2 取整算法 (O(1) 时间与空间复杂度)的更多相关文章

  1. 【转】C语言快速幂取模算法小结

    (转自:http://www.jb51.net/article/54947.htm) 本文实例汇总了C语言实现的快速幂取模算法,是比较常见的算法.分享给大家供大家参考之用.具体如下: 首先,所谓的快速 ...

  2. Raising Modulo Numbers_快速幂取模算法

    Description People are different. Some secretly read magazines full of interesting girls' pictures, ...

  3. 栈(stack)、递归(八皇后问题)、排序算法分类,时间和空间复杂度简介

    一.栈的介绍: 1)栈的英文为(stack)2)栈是一个先入后出(FILO-First In Last Out)的有序列表.3)栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的 ...

  4. log2取整效率测试

    RMQ问题中有个ST算法,当然还有个标准算法.LCA问题可以转化为带限制的RMQ(RMQ+-1)问题来解决.我们姑且认为这些问题的时间复杂度是查询$O(1)$的.但是,注意到对于RMQ(/+-1)问题 ...

  5. 位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  6. 【Java基础】14、位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  7. Powmod快速幂取模

    快速幂取模算法详解 1.大数模幂运算的缺陷: 快速幂取模算法的引入是从大数的小数取模的朴素算法的局限性所提出的,在朴素的方法中我们计算一个数比如5^1003%31是非常消耗我们的计算资源的,在整个计算 ...

  8. 洛谷 P1226 【模板】快速幂||取余运算

    题目链接 https://www.luogu.org/problemnew/show/P1226 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 ...

  9. 《Java语言实现快速幂取模》

    快速幂取模算法的引入是从大数的小数取模的朴素算法的局限性所提出的,在朴素的方法中我们计算一个数比如5^1003%31是非常消耗我们的计算资源的,在整个计算过程中最麻烦的就是我们的5^1003这个过程 ...

  10. 你可能不知道的 JavaScript 中数字取整

    网上方法很多,标题党一下,勿拍 ^_^!实际开发过程中经常遇到数字取整问题,所以这篇文章收集了一些方法,以备查询. 常用的直接取整方法 直接取整就是舍去小数部分. 1.parseInt() parse ...

随机推荐

  1. 点击Popover外区域自动关闭Popover (popover close when click outside)

    $(document).on('click', function (e) { $('[data-toggle="popover"],[data-original-title]'). ...

  2. 介绍 GGUF-my-LoRA

    随着 llama.cpp 对 LoRA 支持的重构,现在可以将任意 PEFT LoRA 适配器转换为 GGUF,并与 GGUF 基础模型一起加载运行. 为简化流程,我们新增了一个名为 GGUF-my- ...

  3. openjdk和jdk的区别与联系

    使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的openjdk,那么到底什么是openjdk,它与sun jdk有什么关系和区别呢?历史上的原 ...

  4. Redis迁移工具之Redis-shake

    Redis-shake is a tool for synchronizing data between two redis databases. Redis-shake是一个用于在两个redis之间 ...

  5. elasticsearch权限验证(Auth+Transport SSL)

    转载:https://knner.wang/2019/11/26/install-elasticsearch-cluster-7-4.html 在新版的Elastic中,基础版(免费)的已经提供了基础 ...

  6. F650A光猫的一些命令(一)

    查看有 / # uname -a Linux F650A 4.1.25 #12 SMP Tue Aug 15 21:57:30 CST 2017 armv7l GNU/Linux / # cat /p ...

  7. ZCMU-1051

    比较来说不太难其实,当然找到一定的公式这与前面的1033相识,都会用到f(i,j)=f(i-1,j)+f(i-1,j-1) 我们可以先从小部分看出来,一层可以整体或者两部分,在面对第i层看前面i-1层 ...

  8. 【Kotlin】协程

    1 前言 ​ 相较于 C# 中的协程(详见 → [Unity3D]协同程序),Kotlin 中协程更灵活,难度更大. ​ 协程是一种并发设计模式,用于简化异步编程,它允许以顺序化的方式表达异步操作,避 ...

  9. 【C#基础】Dynamic类型和正确用法

    前言 Dynamic类型是C#4.0中引入的新类型,它允许其操作掠过编译器类型检查,而在运行时处理. 编程语言有时可以划分为静态类型化语言和动态类型化语言.C#和Java经常被认为是静态化类型的语言, ...

  10. 07C++选择结构(1)

    一.基础知识 1.关系运算符 因为我们要对条件进行判断,必然会用到关系运算符: 名称 大于 大于等于 小于 小于等于 等于 不等于 符号 > >= < <= == != 关系表 ...