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

发布于 2024-10-22 05:00:57 字数 149 浏览 1 评论 0原文

假设我有 n=32。我想知道 log_2(n) 是什么。 在本例中,log_2(32) = 5。

一般来说,计算 2^k 数的对数最快的方法是什么?

IE 给定 n = 2^k。 log_2(n) = b. 查找 B.

允许按位运算。

Say I'm given n=32. I want to know what log_2(n) is.
In this case, log_2(32) = 5.

What is the fastest way in general to compute the log of a 2^k number?

I.e.
Given n = 2^k.
log_2(n) = b.
Find b.

Bitwise operations are permitted.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情定在深秋 2024-10-29 05:00:57

本页提供了六种用 C 语言实现此目的的不同方法;将它们更改为 C# 应该很简单。全部尝试一下,看看哪一个最适合您。

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

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

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]
} 

该解决方案依赖于这样一个事实:2 的前 32 次幂除以 37 时每个都有不同的余数。

如果您需要它对长数进行处理,然后使用 67 作为模数;我让您计算出数组的正确值。

评论者 LukeH 正确地指出,有一个函数据称采用负数的对数(1<<31 是一个负符号整数。)该方法可以修改为采用uint,或者如果给定的数字不满足方法的要求,则可以引发异常或断言。没有给出哪一个是正确的做法;对于此处正在处理的确切数据类型,问题有些模糊。

挑战:

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

如果假设成立,则证明它。如果假设是错误的,则提供一个反例来证明其错误。

This page gives a half-dozen different ways to do that in C; it should be trivial to change them to C#. Try them all, see which is fastest for you.

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

However, I note that those techniques are designed to work for all 32 bit integers. If you can guarantee that the input is always a power of two between 1 and 2^31 then you can probably do better with a lookup table. I submit the following; I have not performance tested it, but I see no reason why it oughtn't to be pretty quick:

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]
} 

The solution relies upon the fact that the first 32 powers of two each have a different remainder when divided by 37.

If you need it to work on longs then use 67 as the modulus; I leave you to work out the correct values for the array.

Commenter LukeH correctly points out that it is bizarre to have a function that purportedly takes the log of a negative number (1<<31 is a negative signed integer.) The method could be modified to take a uint, or it could be made to throw an exception or assertion if given a number that doesn't meet the requirements of the method. Which is the right thing to do is not given; the question is somewhat vague as to the exact data type that is being processed here.

CHALLENGE:

Hypothesis: The first n powers of two each have a different modulus when divided by p, where p is the smallest prime number that is larger than n.

If the hypothesis is true then prove it. If the hypothesis is false then provide a counter-example that demonstrates its falsity.

被你宠の有点坏 2024-10-29 05:00:57

我认为,如果你保证 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;

I think that if you guarantee that n will be a power of 2, a quick way to find b would be by converting n to a binary string and finding the index of 1. Special consideration for case when n = 0

using System.Linq;
...
var binaryStringReversed = Convert.ToString(value, 2).Reverse();
var b = binaryStringReversed.IndexOf("1");

EDIT:

var b = Convert.ToString(value, 2).Length - 1;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文