| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 一种新的高效的寻找字节最低非0位的有效算法 -> 正文阅读 |
|
[数据结构与算法]一种新的高效的寻找字节最低非0位的有效算法 |
一、前言该文章见github仓库:https://github.com/Eureka1024/An-effective-method-for-finding-the-lowest-non-0bit-bit-of-byte 本文目的是介绍一种新的查找字节最低非0位的算法,该算法比一般的位图算法更省空间,同时对于 32bit以及更长的字节,该算法查找字节最低非0位的实现路径也更加高效。 该算法的原理为:假设 X 为 uint32_t 类型的变量, 则 X & (X - 1) ^ X 的算式可以得到仅含字节最低非0位的结果,也就是将所有的可能转变为仅有的32种可能,也就是32个 “1在不同bit位” 的数,接着将这32个数对 37 取余,能够得到互不相同的结果,利用这些结果建立一个位图表,就能实现在O(1)的时间复杂度上查找到目标结果。 我们知道,一个无符号变量,从二进制的角度来看,是由一连串的 0 和 1组成。 以 8 位的字符型变量,是由 8 位的 0 或者 1组成,比如十进制中的 124,在二进制中的表示为 0b01111100(从最低位到最高位分别为 bit0 ~ bit7)。 在一些场景中,比如一些操作系统的调度算法,需要快速求取某个数的字节最低非 0 位,比如上文的 124,其字节最低非 0 位为 bit2,如何快速得到这个位置关系是本文要探讨的问题。 很容易想到使用循环来实现,一个个位检查就行了,但是这样的方法查找效率比较低,时间复杂度达到 O(n)。 在一些 RTOS 中,使用位图的方式,可以在 O(1)的时间复杂度下找到字节最低非0位。 以 RT-Thread 为例,其实现方式如下:
只要将所要求解的值作为这个数组的索引参数,即可得到对应的值。 比如 124,字节最低非 0 位为 bit2,则 rt_lowest_bitmap[124] 的值就是 2。 这种实现方法的好处是可以保证在 O(1)的时间复杂度下,求取目标值。但是这种采取空间换取时间的策略意味着需要大量的空间来制作这个位图表,尤其当变量的类型越来越大时,需要的空间在一些资源比较小的 CPU 中根本无法提供。比如 32bit的变量,需要的空间就高达 2^32 B = 4 GB的大小,如果是 64bit,那就更恐怖了。 本文试图提供一种兼具时间效率与空间效率的查找最低位 1 所处位置的方法。 二、一种新的查找字节最低非0位的方法2.1、原理分析这种方法其实也是使用位图的方式实现,算是一般位图算法的优化。 位图的查找效率已经非常高了,只能将优化的重点放在优化算法使用的空间。 位图的方式之所以需要那么多空间,是因为考虑了该变量的所有情况,比如一个无符号 8bit 字符型有 256 种情况,所以我们的位图就得需要 256B 的空间。 如何优化空间效率呢? 注意到这样一种情况, 0b01001100 和 0b11111100 的字节最低非 0 位的结果是相同的,其实也和 0b00000100 相同,其实算法的目的(求取字节最低非 0 位)已经告诉了我们一个突破点:我们只需要注意字节最低非 0 位即可。这样说来,上文的位图方法就存在使用查找空间冗余的情况。比如我使用 0b00000100 就可以覆盖所有 0bxxxxx100 (x 代表0或1) 的情况。 那么问题来了,如何实现将 0bxxxxx100 转化为 0b00000100 呢? 假设一个无符号的变量名为 value。 通过
将所得的结果再与之前的值异或,即可得到仅剩字节最低非 0 位的情况,即
即最终求得只有一个 1 的情况,利用这种方法,对于无符号字符型,就能够将所求取的情况由判断 256个数转换成判断 8 个数,如果是无符号32位变量,我们能够将 4,294,967,296 个数转换成判断 32个数,这样的差别实在是巨大的。 接下来的问题是如何让简化后要判断的数与字节最低非 0 位建立联系,同样想到使用位图的方式,如何建立位图? 以 8bit 无符号变量为例。 我们的目标是让
因为数组是连续的,如果我们直接使用运算之作为索引值来建立联系,那么空间就和上文提到的位图一样大了。 我们需要使用别的算式使运算结果坍缩到8附近即可。 想到常用的算式:取余操作。 我们对上表中的8个数对 11 进行取余操作,结果如下:
可以得到数组a的值为: 1,2,4,8,5,10,9,7。可以看到,这些数会不相同,可以用来建立联系:
我们可以利用这些数构造出新的位图:
这个位图数组的大小为 11,所以会有三个成员是多余的(值为 X)。 所以最终得到求解
2.2、针对 16 bit 无符号整形变量原理同2.1,取余的数为 19。
2.3、针对 32 bit 无符号整形变量原理同2.1,取余的数为 37。
2.4、针对 64 bit 无符号整形变量原理同2.1,取余的数为 67。
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 3:47:04- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |