计算以2为底整数N的对数log2Nlog_2Nlog2​N 查表法

用于计算以2为底整数N的对数log2Nlog_2Nlog2​N。例如 log28=3log_28=3log2​8=3,log216=4log_216=4log2​16=4。

算法说明

该算法通过查表的方式来计算以2为底整数N的对数log2Nlog_2Nlog2​N。以2为底整数N的对数log2Nlog_2Nlog2​N,与最高有效位(most significant bit set,MSB)的位置相同,例如4 = 0x4 = 0b0100,最高有效位在第2位,与log24=2log_24=2log2​4=2值相等。然后通过查表的方式来计算最高有效位在第几位。32 bit 数最多有 4294967296 种情况,所以生成 32 位数的表来进行查表是不合适的,由于 8 bit 数最多只有 256 个,也就是最多只有 256 种情况,所以通过建 8 bit 数表的方式,然后根据要计算的数的最高有效位在哪个区间,分成 4 种情况来查表计算 log2Nlog_2Nlog2​N 的值。四个区间分别为0 - 7 bit,8 - 15 bit, 16 - 23 bit, 24 - 31 bit 四个区间,我们只计算这 8 bit数的最高有效位是多少,然后将计算值加上对应区间的偏移值 0, 8, 16, 24,得到实际的最高有效位在第几位,也就得到了log2Nlog_2Nlog2​N。

实现代码

实现方式为:

static const char LogTable256[256] =
{-1,0,1, 1,2, 2, 2, 2,3, 3, 3, 3, 3, 3, 3, 3,4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};unsigned int bit_log2(unsigned int val)
{unsigned int ret;unsigned int tmpval1, tmpval2;if ((tmpval2 = (val >> 16))){ret = (tmpval1 = tmpval2 >> 8) ? 24 + LogTable256[tmpval1] : 16 + LogTable256[tmpval2];}else {ret = (tmpval1 = val >> 8) ? 8 + LogTable256[tmpval1] : LogTable256[val];}return ret;
}

注意,如果传入的参数val不是2的次幂,则返回值是val的值向下舍入到最近的2的次幂的对数值。例如 val的值为10,则返回值为log210=3log_210=3log2​10=3。

测试程序:

int main(int argc, char* argv[])
{printf("%d\n", bit_log2(32));printf("%d\n", bit_log2(16));printf("%d\n", bit_log2(8));printf("%d\n", bit_log2(10));printf("%d\n", bit_log2(20));return 0;
}

运行结果如下:

5
4
3
3
4

算法计算过程

该算法通过查表的方式来计算以2为底32 bit整数N的对数log2Nlog_2Nlog2​N。根据要计算的数最高有效位在哪个范围,分成 4 种情况来查表计算 log2Nlog_2Nlog2​N 的值。

第一步,判断要计算的32 bit 整数的高16位(16 - 31 bit)是否有值,有值的话进入第二步,没有的话进入第三步

第二步,判断要计算的数是高8位(24 - 31 bit)是否有值,有值的话将这 8 bit 数进行查表计算,得到的值加上偏移值 24 得到实际的最高有效位;如果高8位(24 - 31 bit)没有值,则将低8位(16 - 23 bit)这 8 bit 数进行查表计算,得到的值加上偏移值 16 得到最高有效位。

第三步,判断要计算的数是32 bit 数的低16位中的高8位(8 - 15 bit)是否有值,有值的话将这 8 bit 数进行查表计算,得到的值加上偏移值 8 得到最高有效位;如果高8位(8 - 15 bit)没有值,则将低8位(0 - 7 bit)这 8 bit 数进行查表计算直接得到最高有效位。

计算示例

例如:

val = 16 = 0x10 = 0b10000,最高有效位在第4位,所以log216=4log_216=4log2​16=4。

模拟这个计算的过程:

0b10000 >>= 16    =>  tmpval2 = 0高16位(16 - 31 bit)没有值0b10000 >>= 8    =>  tmpval1 = 0高8位(8 - 15 bit)没有值LogTable256[val] => LogTable256[16] => 4

结束计算,得到答案4。


[参考资料]

Bit Twiddling Hacks By Sean Eron Anderson


本文链接:https://blog.csdn.net/u012028275/article/details/126843708

【位操作笔记】计算以2为底整数N的对数 查表法相关推荐

  1. crc16modbus查表法_查表法计算CRC16校验值

    /******************************************************************************* * Copyright (c) 201 ...

  2. crc16码表的使用_查表法计算CRC16校验值

    CRC16是单片机程序中常用的一种校验算法.依据所采用多项式的不同,得到的结果也不相同.常用的多项式有CRC-16/IBM和CRC-16/CCITT等.本文代码采用的多项式为CRC-16/IBM: X ...

  3. 常用crc查表法_查表法计算CRC

    (查表法)CRC检验码的计算过程 (1)将上次计算出的CRC校验码右移一个字节: (2)将移出的这个字节与新的要校验的字节进行XOR 运算: (3)用运算出的值在预先生成码表中进行索引,获取对应的值( ...

  4. 常用crc查表法_请教查表法计算CRC的原理

    自己写过的, 希望对你有帮助 Cyclic Redundancy Check(CRC) 原理及实现 /// 1: 需求 在数据传送过程中,为了能够进行错误检测, 往往在数据后追加一些检测码, 当接受方 ...

  5. CRC算法 个人学习笔记 直接法、查表法注意点

    CRC检验码主要是用在数据校验中,用于判断对应数据是否发生传输错误,详细的介绍百度就可以.本文主要是记录我个人在这几天学习使用CRC的过程中遇到的问题.各位在阅读时如果有发现问题,可在评论区留言,谢谢 ...

  6. C语言与,或,非,同或,异或,左移,右移及优先级,查表法计算一个十进制数中1的个数

    1.与:& 2.或:| 3.非:~ 4.异或:^ 5.同或:~^ 6.左移:(<<) 7.右移:(>>) 注意:位运算符中求反运算"~"优先级最高, ...

  7. 【基础知识】CRC(循环冗余校验)直接计算和查表法

    CRC概述 校验 校验是什么,个人理解就是经过一个算法,使用大量数据(几MB的数据)生成较小长度的一串信息(如16Bit),并切要做到 原数据不同时,生成的信息大概率不同(不是加密算法不考虑刻意造数据 ...

  8. QT ModbusCRC16 校验码计算(非查表法,直接计算)

    记录一下QT中如何实现 ModbusCRC16 校验码计算 #include <QCoreApplication> #include <QDebug>//CRC16计算函数 u ...

  9. CRC16计算代码(查表法)

    unsigned short CRC16 (unsigned char *puchMsg,unsigned short usDataLen ) /* 函数以 unsigned short 类型返回 C ...

  10. C语言查表法实现CRC-16计算

    文章目录 函数实现 示例代码 运行结果 函数实现 /*16 bit CRC with polynomial x^16+x^12+x^5+1 */ uint16_t crc16_compute(cons ...

最新文章

  1. (记忆宏)Function问题
  2. 记一次libfreenect2安装配置的经历
  3. vue2.0小示例一个~~新鲜出炉哦。欢迎大家留言
  4. 【STM32】窗口看门狗 WWDG 实验代码详解
  5. 简单易上手的Bootstrap
  6. Spring5的数据访问与集成
  7. Marketing Cloud profile界面功能介绍
  8. SPI模式下MCU对SD卡的控制及操作命令
  9. Http\Https\Socket
  10. jQuery之.queue()
  11. python读写不同编码txt文件
  12. Android 微信分享后留在微信,没有回调的问题解决方案
  13. iOS Crash类别总结
  14. LEADBBS 不要验证码
  15. 运行spark及hadoop版本不一致解决方法
  16. 第七届山东理工大学ACM趣味编程循环赛 Round#2 sdut4120 城堡问题
  17. GPU 共享内存地址映射方式
  18. 【jzoj5289】【NOIP2017提高组A组模拟8.17】【偷笑】【数据结构】
  19. sqli-labs第十三关--十五关
  20. 喜欢的现代诗 -。-

热门文章

  1. 面试你对计算机未来三年内规划,2019农商银行面试:谈谈你未来3年的规划
  2. HBuilder X详细教程
  3. coding部署博客 + 腾讯云 cdn 踩坑日记
  4. U盘拔出时总是提示有程序正在使用?
  5. ZigBee组网实验:多终端节点向协调器发送数据amp;协调器给终端节点发送数据
  6. 正则表达式系列 (一)
  7. 美国大学计算机理论专业phd,盘点美国那些计算机专业PHD超级难申请的大学
  8. java发微信字体颜色_java微信公众号发送消息模板
  9. excel 第2讲:单元格格式设置
  10. 如何在Microsoft Word里面插入图片作为背景/封面?