无符号整形二进制
1数量
- 目标:统计 unsinged二进制表示中1数量
- 思路方向- 移位遍历
- 分治统计
 
仅遍历1
| 1 | int population(unsigned int bits){ | 
- 遍历减少:仅仅遍历无符号整形二进制表示中 1次数- bits &= bits - 1将末尾- 1消除
 
分治+查表
| 1 | int * initialization(){ | 
- 思路- 建表:为 8bits 数建立 256 长度的 1数量表- 递推建立:f(n) = f(n >> 1) + last_bit(n)
 
- 递推建立:
- 分治:将无符号整型分4块查表、加和结果
 
- 建表:为 8bits 数建立 256 长度的 
分治
| 1 | int population(unsigned int bits){ | 

- 分治统计:依次将相邻 2bits、 4bits 分组,计算组内 1数量- 移位、求并:将组内无效 bits 置 0、并对齐
- +:计算组内- 1数量- 0x0 + 0x0 = 0x0
- 0x0 + 0x1 = 0x1
- 0x1 + 0x1 = 0x10:进位,符合逻辑
 
 
- 移位、求并:将组内无效 bits 置 
- 改进方式:考虑避免不必要的 &- 根据进位特性替换 2bits 组对应语句
- 考虑组内空位是否可容纳 +后结果- 8bits 组:有效半组 4bits 足够存储中的最大 1数量 8,但 无法存储 16 或更大, 需要及时置空无效bit
- 16bits 组及之后:有效半组足够存储最大 1数量 32,可以 计算完之后再取值
 
- 8bits 组:有效半组 4bits 足够存储中的最大 
 
| 1 | int population(unsigned int bits){ | 
奇偶性
- 目标:判断 unsigned二进制表示中1数量奇偶性
- 思路方向- 移位遍历,注意语言特性- 逻辑移位和算术移位
- 求余结果
 
- 分治统计
 
- 移位遍历,注意语言特性
分治统计
| 1 | // 原始版本 | 
- 分治统计:依次将相邻 2bits、 4bits 分组,统计组内奇偶性- 分组方式顺序调换仅影响中间结果中存放奇偶性统计结果 bits 位置- 奇偶性统计结果存放在组内最后 bit
- 其中每次分组统计事实上都是统计 2bits 的奇偶性
 
 
- 分组方式顺序调换仅影响中间结果中存放奇偶性统计结果 bits 位置
- 改进方式- 调整分组顺序,将存储奇偶性 bits 位置移至最后
- 计算奇偶性 bits 对应奇偶性表,查表得到结果- 一般可以设置长度为 0x0f长度的数组,其中取值为索引奇偶性
- 0x6996即为对应奇偶性表,其中各位序 bit 取值为位序值对应 的奇偶性
 
- 一般可以设置长度为 
 
| 1 | // 改进版本 | 
奇偶性填充
- 目标:将 unsigned char中最高位作为校验位,保证整体的二进制标表示的奇偶性
- 思路方向- 求1数量并设置标志位
- 按位乘积后取模
 
- 求
取模
| 1 | unsigned char even(unsigned char i){ | 
- 各数字二进制含义(设 i的二进制表示为abcdefg)- 0x10204081 * i得到- i二进制重复 5 次(溢出被截断)
- 0x888888ff &抽取所需 bits- d000a000e000b000f000c000gabcdefg
- 1920 = 15 * 128:对其取模即得到- [X]abcdefg(将被除数表示为 16 进制分块可证)
 
位元反序
- 目标:返回 6bits 长二进制的反序
| 1 | unsigned char revert(unsigned char i){ | 
- 各数字二进制含义(设 i的二进制表示为abcdef)- 0x00082082 * i得到- i二进制重复 4 次
- 0x01122408 &抽取所需 bits- 0000000a000e00b000f00c000000d000
- 对 255取模即得到反序*(将被除数表示为 256 进制分块可证)
 
前导 0
- 目标:获取 unsigned的二进制表示中前导0数量
- 思路方向- 移位遍历
- 区间映射:将原始 unsigned映射为较小范围的取值
 
区间映射
| 1 | unsigned char nlz(unsigned int i){ | 
- 区间映射- 移位取或:将最高位 1传播至所有低位,原始值映射至 33 种取值
- 0x06eb14f9:将 33 种值映射为低 6 位取值均不同值- 此类数的共同特点是因子均为 $2^k \pm 1$ (此类数乘法容易通过移位操作实现)
- 最小的此性质的数为 0x45bced1 = 17 * 65 * 129 * 513
 
 
- 移位取或:将最高位 
速算
无符号整形除法
- 目标:大部分计算机架构中除法耗时,寻找方法将特定除数的除法转换为 其他指令
- 思路:除数为常数时,用移位、乘法、加法替代除法运算- 常数除法(有符号或无符号)基本都有对应的乘法版本
- 注意类型溢出
 
除数为3
| 1 | unsigned div3(unsigned int i){ | 
快速求平方根倒数
| 1 | float i_sqrt(float a){ | 
- 移位获取初始值 - 考虑(规格化)单精度浮点数 $a$ 的二进制表示 
- 则 - 0x5f000000 - (ii >> 1)可以满足指数部分得到近似结果 $190 - \frac E 2$
- 其他细节使得存在比 0x5f000000实践更优值,如:0x5f375a86- 规格化值的底数接近 1
- 移位运算指数最后位部分移至尾数
- 减法运算尾数部分向指数借位
 
 
- 牛顿法:$x{n+1} = xn - \frac {f(x_n)} {f^{‘}(x__n)}$ - 求 $\frac 1 {\sqrt x}$,即求 $f(x) = x^{-2} - a$ 零点
- 则迭代为 $x{n+1} = xn(1.5 - 0.5 a x__n^2)$
 












