variable precision SWAR算法

简介: variable precision SWAR算法

     计算二进制形式中1的数量这种问题,在各种刷题网站上比较常见,以往都是选择最笨的遍历方法“蒙混”过关。在了解Redis的过程中接触到了variable precision SWAR算法(以下简称VP-SWAR算法),算法异常简洁,是目前已知的同类方法中最快的。但如果对于位运算不是很熟悉的话,却不一定容易理解,所以有必要记录一下。

     下面先看看VP-SWAR算法的完整实现,然后再逐行解释。

public int vpSWAR(int i){
    i = (i & 0x55555555) + ((i>>1) & 0x55555555);
    i = (i & 0x33333333) + ((i>>2) & 0x33333333);
    i = (i & 0x0F0F0F0F) + ((i>>4) & 0x0F0F0F0F);
    i = (i * 0x01010101) >> 24;
    return i;
  }

     VP-SWAR算法分为四步,第一步

i = (i & 0x55555555) + ((i>>1) & 0x55555555);

     第一步的作用是计算每两位为一组的二进制形式包含1的个数。要理解这句话,我们需要从二进制的角度看看到底发生了什么。首先, 0x55555555 的二进制表示为 0101 0101 0101 0101 0101 0101 0101 0101 ,这个数字的规律是基数位为1,偶数位为0。为简单起见,我们只考虑两位,总共有四种情况,即:

i b i & b 结果
00 01 00
01 01 01
10 01 00
11 01 01

      观察发现, i & (0b01) 是i的基数位对应b的1位,i的偶数位对应着b的0位, i & (0b01) 的结果会将I的偶数位置为0,而基数位保持不变,得到的结果就是i的基数位包含1的个数。 (i >> 1) & 0x55555555 先将i右移一位,也就是将i的基数位对应b的0位,i的偶数位对应着b的1位,然后再与 0x55555555 按位与,计算出来的是i的偶数位包含1的个数。两个计算结果相加就得到i每两位为一组中包含的1的数量,我们最后需要的就是这每两位一组的和。

     第二步是在第一步的基础上,计算每四位为一组包含1的个数。按照每2位为一组分组用到了 0x55555555 这个数,那么自然的,按照每4位为一组分组自然就需要 0b0011 这种形式,这就是使用 0x33333333 的原因。理论上, i & (0b0011) 总共有16种情况,但是四位二进制位最多包含4个1,用二进制表示为 0b0100 ,所以经过第一步之后,i最多有5种取值,如下:

i b i & b 结果
0000 0011 0000
0001 0011 0001
0010 0011 0010
0011 0011 0011
0100 0011 0000

     观察发现, i & (0b0011) 得到的是i的低两位包含的1的个数, (i >> 2) & 0b0011 )得到的是i的高两位包含的1的个数,两个结果相加得到每四位包含的1的个数。注意,这里并不是说任何数与 0b0011 按位与得到的都是低两位包含的1的个数,这里的前提是第一步的计算,因为经过第一步计算之后,每两位包含多少个1已经记录了下来,再和 0b0011 按位与才得到正确的结果。例如, 0x0010 & 0x 0011=0x0010 ,但是我们不能说 0x0010 包含两个1,但是如果 0x0010 是经过第一步的计算得来,那才说明 0x0010 记录原始数据低两位有两个1。

     第三步在第二步基础上,计算每8位有多少个1,由 0x010x0011 ,很自然想到 0x00001111 ,其对应的32位的十六进制数就是 0x0F0F0F0F

     第四步就很有意思了,它不再是计算每16位包含1的个数,而是直接计算32位包含1的个数。对于32位的数来说,可以将其按每8位一组分为4组,分别用ABCD表示,例如 0x01020304 用这种形式表示为:

     假设 0x01020304 是经过前三步计算之后得到的结果,那么要计算其总共包含多少个1,只需计算A+B+C+D。而ABCD表示的是不同的位区间范围,不能直接相加,该如何快速计算A+B+C+D的值呢?这里又用到了移位运算,将B、C、D分别左移8位、16位、24位,使其分别与A对齐:

      我们发现,将数字i分别左移0位、8位、16位、24位然后相加的结果,就是 i * 0x01010101 ,因为 i + (i << 8) + (i << 16) + (i << 24) = i * (1 + 1 << 8 + 1 << 16 + 1 << 24) = i * 0x01010101 。对于32位数字来说,左移之后超过32位的部分会被舍弃,低位补0,将左移之后得到的四个数字相加,结果的高8位的值就是原32位数包含的1的个数,要得到这个值,只需要将结果右移24位,将值放在低8位即可。

     到这里,整个算法就结束了,右移的结果就是1的数量。在Redis中,BITCOUNT命令同时使用了查表法和VP-SWAR这两种方法。当要计算的位数小于128位时,使用查表法,否则使用VP-SWAR算法。其中查表法的做法是,程序先存一个256长度的表,按顺序记录从0-255(即 0b00000000 - 0b11111111) 数中二进制1的个数,然后对于输入参数每8位查一次表。

相关文章
|
算法
variable-precision SWAR算法介绍
variable-precision SWAR算法介绍
288 0
|
13天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
145 80
|
1天前
|
机器学习/深度学习 数据采集 算法
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a实现时间序列预测,采用CNN-GRU-SAM网络结构。卷积层提取局部特征,GRU层处理长期依赖,自注意力机制捕捉全局特征。完整代码含中文注释和操作视频,运行效果无水印展示。算法通过数据归一化、种群初始化、适应度计算、个体更新等步骤优化网络参数,最终输出预测结果。适用于金融市场、气象预报等领域。
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
|
1天前
|
算法
基于龙格库塔算法的锅炉单相受热管建模与matlab数值仿真
本设计基于龙格库塔算法对锅炉单相受热管进行建模与MATLAB数值仿真,简化为喷水减温器和末级过热器组合,考虑均匀传热及静态烟气处理。使用MATLAB2022A版本运行,展示自编与内置四阶龙格库塔法的精度对比及误差分析。模型涉及热传递和流体动力学原理,适用于优化锅炉效率。
|
6天前
|
机器学习/深度学习 算法
基于遗传优化的双BP神经网络金融序列预测算法matlab仿真
本项目基于遗传优化的双BP神经网络实现金融序列预测,使用MATLAB2022A进行仿真。算法通过两个初始学习率不同的BP神经网络(e1, e2)协同工作,结合遗传算法优化,提高预测精度。实验展示了三个算法的误差对比结果,验证了该方法的有效性。
|
9天前
|
机器学习/深度学习 数据采集 算法
基于PSO粒子群优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目展示了基于PSO优化的CNN-GRU-SAM网络在时间序列预测中的应用。算法通过卷积层、GRU层、自注意力机制层提取特征,结合粒子群优化提升预测准确性。完整程序运行效果无水印,提供Matlab2022a版本代码,含详细中文注释和操作视频。适用于金融市场、气象预报等领域,有效处理非线性数据,提高预测稳定性和效率。
|
5天前
|
算法
基于梯度流的扩散映射卡尔曼滤波算法的信号预处理matlab仿真
本项目基于梯度流的扩散映射卡尔曼滤波算法(GFDMKF),用于信号预处理的MATLAB仿真。通过设置不同噪声大小,测试滤波效果。核心代码实现数据加载、含噪信号生成、扩散映射构建及DMK滤波器应用,并展示含噪与无噪信号及滤波结果的对比图。GFDMKF结合非线性流形学习与经典卡尔曼滤波,提高对非线性高维信号的滤波和跟踪性能。 **主要步骤:** 1. 加载数据并生成含噪测量值。 2. 使用扩散映射捕捉低维流形结构。 3. 应用DMK滤波器进行状态估计。 4. 绘制不同SNR下的轨迹示例。
|
10天前
|
机器学习/深度学习 算法 索引
单目标问题的烟花优化算法求解matlab仿真,对比PSO和GA
本项目使用FW烟花优化算法求解单目标问题,并在MATLAB2022A中实现仿真,对比PSO和GA的性能。核心代码展示了适应度计算、火花生成及位置约束等关键步骤。最终通过收敛曲线对比三种算法的优化效果。烟花优化算法模拟烟花爆炸过程,探索搜索空间,寻找全局最优解,适用于复杂非线性问题。PSO和GA则分别适合快速收敛和大解空间的问题。参数调整和算法特性分析显示了各自的优势与局限。
|
4天前
|
算法 5G
基于MSWA相继加权平均的交通流量分配算法matlab仿真
本项目基于MSWA(Modified Successive Weighted Averaging)相继加权平均算法,对包含6个节点、11个路段和9个OD对的交通网络进行流量分配仿真。通过MATLAB2022A实现,核心代码展示了迭代过程及路径收敛曲线。MSWA算法在经典的SUE模型基础上改进,引入动态权重策略,提高分配结果的稳定性和收敛效率。该项目旨在预测和分析城市路网中的交通流量分布,达到用户均衡状态,确保没有出行者能通过改变路径减少个人旅行成本。仿真结果显示了27条无折返有效路径的流量分配情况。
|
1月前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。

热门文章

最新文章