计算log_2(n)的最快方法,其中n是2 ^ k的形式?

时间:2011-03-17 14:40:49

标签: c# math bit-manipulation

说我给了n = 32。我想知道log_2(n)是什么。 在这种情况下,log_2(32)= 5。

计算2 ^ k数字日志的最快方法是什么?

即。 给定n = 2 ^ k。 log_2(n)= b。 找到b。

允许按位操作。

2 个答案:

答案 0 :(得分:15)

这个页面提供了六种不同的方法来做到这一点;将它们改为C#应该是微不足道的。全部尝试,看看哪个最快。

http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious

但是,我注意到这些技术旨在用于所有 32位整数。如果您可以保证输入始终 2的幂,介于1和2 ^ 31之间,那么您可以使用查找表做得更好。我提交以下内容;我没有对它进行性能测试,但我认为没有理由说它不应该很快:

static int[] powers = new[] {0, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 
                        30, 28, 11, 0, 13, 4, 7, 17, 0, 25, 22, 
                        31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 
                        20, 8, 19, 18};

static int Log2OfAPower(int x)
{
    return powers[((uint)x) % 37]
} 

解决方案依赖的事实是,当除以37时,前两个的32个幂都有不同的余数。

如果你需要它来长时间工作,那么使用67作为模数;我让你为数组找出正确的值。

评论者LukeH正确地指出,拥有一个据称取负数的日志(1<<31是负的有符号整数)的函数是奇怪的。)该方法可以被修改为取一个uint,或者它如果给出的数字不符合方法的要求,可以使异常或断​​言抛出。没有给出哪个是正确的做法;关于这里正在处理的确切数据类型,这个问题有些模糊。

CHALLENGE:

假设:当除以p时,每个2的前n个幂具有不同的模数,其中p是大于n的最小素数。

如果假设为真,则证明它。如果假设是假的,那么提供一个证明其虚假的反例。

答案 1 :(得分:1)

我认为,如果您保证n将是2的幂,则快速查找b的方法是将n转换为二进制字符串并查找索引1. n = 0

时的特殊情况
using System.Linq;
...
var binaryStringReversed = Convert.ToString(value, 2).Reverse();
var b = binaryStringReversed.IndexOf("1");

编辑:

var b = Convert.ToString(value, 2).Length - 1;