本文发布于游戏程序员刘宇的个人博客, 转载请注明来源https://www.cnblogs.com/xiaohutu/p/10950011.html

某天我在优化游戏的算法,在将一个个关键数据结构优化全部成位操作后,最终来到最后一座大山前,如何快速计算出这个数值的二进制表示中最后一位的1在哪一位?

首先,我们已知:

将二进制只保留最后一位1的算法:

v & -v 的原理
已知IEEE对有符号整数中负数的定义是所有数值位取反+,首位填1,首位这样正负数加起来既可以为0。
例如:一个8位的整数
A = , 取反 , 取反加1 ,首位填1得到 -A =
A + -A 正好加到最高一位进位后为 因为取反的时候加1,所以A最后一个为1的位取反后为0,下面我们称为第N位
取反后的第N位为0,后面全为1,再加1后的数值上第N位变成1,后面全为0
此时A和-A里,第N位之后的位全为0,第N位之前的位全为反
所以两个数进行与操作,只有第N位为1
即: & =

那么,如何将v&-v转换成N呢?

德布莱英序列

我看到了一段代码:

unsigned int v;
int r;
static const int MultiplyDeBruijnBitPosition[] =
{
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , ,
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> ];

计算过程可以理解为:

将0x077CB531U的二进制:

00000111011111001011010100110001

乘以 v&-v,即左移N位,再右移27位,得到的常数在MultiplyDeBruijnBitPosition里查表,得到的结果即是N。

例如乘以  ,(6个0,左移6位)

->
再右移27位
->
得到的数字是27,在数组里是6

很神奇,不是吗?

仔细分析一下这个数字,可以发现,这个数字从每一位分别开始看,连续5位(到结尾循环),是所有5位的二进制数字的全集,而且左移28-31位时,结尾填0,正好序列开始的几个数字也是0。

那么不难理解,从这个数列的第X位任意取5位,都可以得到一个0-31的数字,并且根据查表取出这个数字对应是左移过几位。

为什么会存在这样的序列

把二进制依次写出,如果是两位,我们让每个两位数字的最后一位等于下一个两位数字的第一位, 00-01-11-10,写出 0011,长度为4。

三位,我们让每个三个数字的后两位等于下一个数字前两位,001-011-111-110-101-010-000,写出00111010,长度为8。

四位,见图:

依此类推,到第N位,我们可以让每个数的后N-1位等于下一个数字的前N-1位,得到长度为 2的N次方长度的2进制序列。

这就是德布莱英原理:一定存在长度为2的N次方长度的二进制串,循环来看,一位位移动,可以完整描述所有N位长度的二进制数字的集合。

链接1:https://en.wikipedia.org/wiki/De_Bruijn_sequence

链接2:https://baike.baidu.com/item/德布莱英序列/18898516?fr=aladdin

我们可以任意生成这样的序列吗

稍微经过研究可以发现,Debrujin序列是密码学中运用很广泛的序列,已知原理,可以编程来实现自动求序列的代码。

1. 暴力遍历

2. 递归法 https://blog.csdn.net/lusongno1/article/details/51104737

3. 本原多项式方法 https://blog.csdn.net/sea_sky_cloud/article/details/80932402

神秘常量0x077CB531,德布莱英序列的恩赐的更多相关文章

  1. 神秘常量复出!用0x077CB531计算末尾0的个数 -- De Bruijn 序列

    http://www.matrix67.com/blog/archives/3985 神秘常量复出!用0x077CB531计算末尾0的个数 大家或许还记得 Quake III 里面的一段有如天书般的代 ...

  2. 神秘常量!用0x077CB531计算末尾0的个数,32位数首位相连

    大家或许还记得 Quake III 里面的一段有如天书般的代码,其中用到的神秘常量 0x5F3759DF 究竟是怎么一回事,着实让不少人伤透了脑筋.今天,我见到了一段同样诡异的代码.     下面这个 ...

  3. Ural2004: Scientists from Spilkovo(德布鲁因序列&思维)

    Misha and Dima are promising young scientists. They make incredible discoveries every day together w ...

  4. 德布鲁因序列与indexing 1

    目录 写在前面 标记left-most 1与right-most 1 确定位置 德布鲁因序列(De Bruijn sequence) 德布鲁因序列的使用 德布鲁因序列的生成与索引表的构建 参考 博客: ...

  5. De Bruijn序列

    最近文章中经常出现及De Bruijin 这个关键字,网上搜索了一下,记录下来. De Bruijn序列 (德布鲁因序列) 问题:能否构造一个长度为2的n次方的二进制环状串,使得二进制环状串中总共2的 ...

  6. Java程序员必备英文单词

    列表中共有769个单词,这些单词是从JDK.Spring.SpringBoot.Mybatis的源码中解析得到,按照在源码中出现的频次依次排列,页面中的单词是出现频次大于1000的.单词的音标.翻译结 ...

  7. 自然语言处理中的自注意力机制(Self-attention Mechanism)

    自然语言处理中的自注意力机制(Self-attention Mechanism) 近年来,注意力(Attention)机制被广泛应用到基于深度学习的自然语言处理(NLP)各个任务中,之前我对早期注意力 ...

  8. [NLP/Attention]关于attention机制在nlp中的应用总结

    原文链接: https://blog.csdn.net/qq_41058526/article/details/80578932 attention 总结 参考:注意力机制(Attention Mec ...

  9. 普适注意力:用于机器翻译的2D卷积神经网络,显著优于编码器-解码器架构

    现有的当前最佳机器翻译系统都是基于编码器-解码器架构的,二者都有注意力机制,但现有的注意力机制建模能力有限.本文提出了一种替代方法,这种方法依赖于跨越两个序列的单个 2D 卷积神经网络.该网络的每一层 ...

随机推荐

  1. 2018-12-25-WPF-如何在-WriteableBitmap-写文字

    title author date CreateTime categories WPF 如何在 WriteableBitmap 写文字 lindexi 2018-12-25 09:13:57 +080 ...

  2. MockMvc control层单元测试 参数传递问题

    GET: 1.路径参数@PathVariable 2.表单参数@RequestParam POST: 1.JSON请求体参数 @RequestBody 放: 1.路径参数@PathVariable 2 ...

  3. Linux 内核存取配置空间

    在驱动已探测到设备后, 它常常需要读或写 3 个地址空间: 内存, 端口, 和配置. 特别 地, 存取配置空间对驱动是至关重要的, 因为这是唯一的找到设备被映射到内存和 I/O 空间的位置的方法. 因 ...

  4. HTML自制计算器

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. 2018-2-13-win10-uwp-csdn-博客阅读器

    title author date CreateTime categories win10 uwp csdn 博客阅读器 lindexi 2018-2-13 17:23:3 +0800 2018-2- ...

  6. Wannafly挑战赛25 因子 [数论]

    一.题意 令 X = n!, 给定一大于1的正整数p 求一个k使得 p ^k | X 并且 p ^(k + 1) 不是X的因子 输入为两个数n, p (1e18>= n>= 10000 & ...

  7. stm32外部时钟源8M换成12M后库函数相应修改总结

    前言 在做“自制继电器上位机控制软件”项目的时候,下位机用到USB虚拟串口,将以前写好的USB虚拟串口程序移植到下位机,发现程序计算机无法识别到虚拟串口STMicroelectronics Virtu ...

  8. .data()与.detach()的区别

    .data()和.detach()都可以获取Variable内部的Tensor,但.detach()更加安全 https://zhuanlan.zhihu.com/p/38475183

  9. 分布式大牛详解Zookeeper底层原理

    很多学员都在反馈,说zk很难学,学的不是很明白,在这里,我继续带着大家详解一遍Zookeeper 首先zk是什么呢首先肯定是一个个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用 ...

  10. WeihanLi.Npoi 1.7.0 更新

    WeihanLi.Npoi 1.7.0 更新介绍 Intro 昨天晚上发布了 WeihanLi.Npoi 1.7.0 版本,增加了 ColumnInputFormatter/ColumnOutputF ...