- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用“De Bruijn”算法来发现大数(最多 64 位)的二进制位数。
例如:
我发现使用基于 De Bruijn 的表查找让我能够以比传统方法(幂、平方、...)快 100 倍的速度进行计算。
根据 this website , 2^6 有计算64位数字的表格。这将是在 c# 中公开的表
static readonly int[] MultiplyDeBruijnBitPosition2 = new int[64]
{
0,1,2,4,8,17,34,5,11,23,47,31,63,62,61,59,
55,46,29,58,53,43,22,44,24,49,35,7,15,30,60,57,
51,38,12,25,50,36,9,18,37,10,21,42,20,41,19,39,
14,28,56,48,33,3,6,13,27,54,45,26,52,40,16,32
};
(我不知道我从那个网站拿来的表格是否正确)然后,基于 R.. 评论 here .我应该使用它来使用带有输入 uint64 数字的表。
public static int GetLog2_DeBruijn(ulong v)
{
return MultiplyDeBruijnBitPosition2[(ulong)(v * 0x022fdd63cc95386dull) >> 58];
}
但 C# 编译器不允许我使用“0x022fdd63cc95386dull”,因为它会溢出 64 位。我必须改用“0x022fdd63cc95386d”。
使用这些代码。问题是我没有得到给定输入的正确结果。
例如,对数字进行 1.000.000 次计算:17012389719861204799(使用 64 位)这是结果:
我试图了解“De Bruijn”的工作原理,以及如何解决此问题并为 C# 创建最终代码以计算最多 64 位数字。
UDPATE 和不同解决方案的基准
我一直在寻找最快的算法来获取在 C# 中给定的无符号 64 位数字的二进制位数(称为 ulong)。
例如:
2 和平方的常规幂非常慢。仅对于 10000 次计算,它需要 1500 毫秒才能得到答案。 (100M 计算需要数小时)。
在这里,Niklas B. , Jim Mischel , 和 Spender带来了不同的方法来加快速度。
使用 Windows 7(64 位)超频至 3Ghz 的 CPU Q6600 测试此方法给出以下结果。
如您所见,只需几秒钟即可正确找到给定的 100,000,000 个请求,是最快的 De_Bruijn 128 位版本。
非常感谢大家,你们在这方面帮了我很多。我希望这对你也有帮助。
最佳答案
你应该检查R..'s answer和 his resource再次。他回答的问题是如何找到 2 的幂 的 log2。
bit twiddling 网站说简单的乘法 + shift 只适用于“如果你知道 v 是 2 的幂”。否则你需要 round up to the next power of two第一:
static readonly int[] bitPatternToLog2 = new int[64] {
0, // change to 1 if you want bitSize(0) = 1
1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
}; // table taken from http://chessprogramming.wikispaces.com/De+Bruijn+Sequence+Generator
static readonly ulong multiplicator = 0x022fdd63cc95386dUL;
public static int bitSize(ulong v) {
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
// at this point you could also use popcount to find the number of set bits.
// That might well be faster than a lookup table because you prevent a
// potential cache miss
if (v == (ulong)-1) return 64;
v++;
return MultiplyDeBruijnBitPosition2[(ulong)(v * multiplicator) >> 58];
}
这是一个具有更大查找表的版本,避免了分支和一次添加。我使用随机搜索找到了魔数(Magic Number)。
static readonly int[] bitPatternToLog2 = new int[128] {
0, // change to 1 if you want bitSize(0) = 1
48, -1, -1, 31, -1, 15, 51, -1, 63, 5, -1, -1, -1, 19, -1,
23, 28, -1, -1, -1, 40, 36, 46, -1, 13, -1, -1, -1, 34, -1, 58,
-1, 60, 2, 43, 55, -1, -1, -1, 50, 62, 4, -1, 18, 27, -1, 39,
45, -1, -1, 33, 57, -1, 1, 54, -1, 49, -1, 17, -1, -1, 32, -1,
53, -1, 16, -1, -1, 52, -1, -1, -1, 64, 6, 7, 8, -1, 9, -1,
-1, -1, 20, 10, -1, -1, 24, -1, 29, -1, -1, 21, -1, 11, -1, -1,
41, -1, 25, 37, -1, 47, -1, 30, 14, -1, -1, -1, -1, 22, -1, -1,
35, 12, -1, -1, -1, 59, 42, -1, -1, 61, 3, 26, 38, 44, -1, 56
};
static readonly ulong multiplicator = 0x6c04f118e9966f6bUL;
public static int bitSize(ulong v) {
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
return bitPatternToLog2[(ulong)(v * multiplicator) >> 57];
}
你绝对应该检查other tricks to compute the log2并考虑使用 MSR
如果您使用的是 x86(_64),请使用汇编指令。它为您提供了最高有效位的索引,这正是您所需要的。
关于c# - De Bruijn 算法二进制数字计数 64 位 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21888140/
我注意到我可以在某些地方*这些语言之间进行选择: de - 德语 - Deutsch de-DE - Deutsch(Deutschland) - 德语(德国) *Android 初始设备设置,语言设
我运行以下代码并得到评论中显示的结果。我知道 == 和 .equals() 之间的区别。我不明白的是为什么我在第二行的代码与第三行的代码有不同的结果。 String de = "de"; //
在我的 WPF 应用程序中,CurrentUICulture 未被 Windows 正确接管或错误地存储在 Windows 中。 Windows 中的区域和语言设置在我找到“Deutsch (Schw
我有一个项目,我只能在 下添加代码-tag 但重要的是语言在 SEO 和其他一些东西的标题中。 所以我的问题是: 什么是优先级/排名 对比 最佳答案 根据 Google Multi-region
通过 Kendo.culture('de-DE') 更改应用程序中的文化,默认设置为 en-US。但是,当文化为“de-DE”时,进行简单的文化更改会弄乱值,它将网格值乘以 100。 有谁知道值乘以
const EUR = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }) const a = EUR.for
我在我的 asp.net 应用程序中使用德语 UI Culture。我正在根据下拉列表中选择的语言更改我的应用程序的 UI 区域性,在下拉列表中选择的索引更改我正在使用此代码 Thread.Curre
我正在通过建立一份CosmWasm合同来教自己Rust。。游戏的定义是。(Slot是另一个结构,而GameStatus是一个枚举,前缀都是它们自己的#[派生...宏。)。我定义了一个游戏地图,如下所示
使用 el = de.query(By.css('h2')).nativeElement; 有什么好处吗?通过 el = de.nativeElement.querySelector('h2'); 的
在 pear.phpunit.de/PHPUnit 中安装 PHPUnit 未知 channel pear.phpunit.de 时出错 无效的包名称/包文件 "Debian-4 操作系统上的 pea
'[abc]%' 搜索以 a、b 和 c 开头的单词,但我想搜索两个不同的两个字符 SB 和 TB。 以下代码返回 nth。 SELECT v.sku FROM sylius_product_vari
Caused by: java.lang.IllegalArgumentException: El mapeo de filtro especifica un nombre desconocido d
本文整理了Java中de.schildbach.pte.ZvvProvider类的一些代码示例,展示了ZvvProvider类的具体用法。这些代码示例主要来源于Github/Stackoverflow
我有一个正则表达式 [a-zA-Z][a-z] 我必须更改此正则表达式,以便正则表达式不接受以“de”、“DE”、“dE”和“De”开头的字符串。我无法使用后视或前视,因为我的系统不支持是吗? 最佳答
我有一个正则表达式 [a-zA-Z][a-z] 我必须更改此正则表达式,以便正则表达式不接受以“de”、“DE”、“dE”和“De”开头的字符串。我无法使用后视或前视,因为我的系统不支持是吗? 最佳答
我有两个这样的字符串 string s = "abcdef"; string t = "def"; 我想从 s 中删除 t。我可以这样做吗? s = s - t? 编辑 我将有两个字符串 s 和 t,
我正在制作一个解密维吉尼亚密码的程序。用户只能给出字母键。 for (int i = 0, counter = strlen(text); i < counter; i++) {
希望获得 Java 遵循的一些幕后内存引用和规则。 这是一段代码。基本上,此类用于实例化一些其他对象 (MyOtherObject),然后将此对象的 doClose() 方法的引用发送到 Vector
我有一个包含 的对象 公共(public)类 PositionsChannelApplicationGroups { public PositionsChannelApplicationGroups(
我整个星期都在用一个具有挑战性的设计来解决它,我正在完成我的最后一件抵抗运动,今天还剩一个小时, 我这里有一个菱形/蜂窝状的用户界面 http://jsfiddle.net/z42wg/25/ .di
我是一名优秀的程序员,十分优秀!