Algorithm 计算一个整数x以2为底的对数的最佳方法是什么?该对数近似于小于或等于它的最大整数?
在计算基数2的下限(log(x))的算法中,计算下限(log(x))的最佳摊销时间复杂度是多少?计算对数有许多不同的算法,每种算法都代表某种不同的折衷。这个答案调查了各种方法和一些涉及的权衡 方法1:迭代乘法 一种简单的计算方法⌊logb n⌋ 计算序列b0,b1,b2等,直到我们找到一个大于n的值。在这一点上,我们可以停止,并返回在此之前的指数。这方面的代码相当简单:Algorithm 计算一个整数x以2为底的对数的最佳方法是什么?该对数近似于小于或等于它的最大整数?,algorithm,time-complexity,computer-science,logarithm,Algorithm,Time Complexity,Computer Science,Logarithm,在计算基数2的下限(log(x))的算法中,计算下限(log(x))的最佳摊销时间复杂度是多少?计算对数有许多不同的算法,每种算法都代表某种不同的折衷。这个答案调查了各种方法和一些涉及的权衡 方法1:迭代乘法 一种简单的计算方法⌊logb n⌋ 计算序列b0,b1,b2等,直到我们找到一个大于n的值。在这一点上,我们可以停止,并返回在此之前的指数。这方面的代码相当简单: x = 0; # Exponent bX = 1; # b^Exponent while (bx <= n)
x = 0; # Exponent
bX = 1; # b^Exponent
while (bx <= n) {
x++;
bX *= b;
}
return x - 1;
问题是如何进行二进制搜索来解决问题。具体来说,我们知道b2x太大了,但我们不知道有多大。与“猜数字”游戏不同,指数上的二进制搜索有点棘手
一个可爱的解决方案是基于这样一个想法:如果x是我们正在寻找的值,那么我们可以将x写为二进制的一系列位。例如,让我们写x=am-12m-1+am-22m-2+…+a121+a020。然后
bx=bam-12m-1+am-22m-2+…+a121+a020
=2am-12m-1·2am-22m-2·2a0 20
换句话说,我们可以通过一次一点地构建x来尝试发现bx是什么。为此,当我们计算b1、b2、b4、b8等值时,我们可以记下我们发现的值。然后,一旦我们超出了范围,我们可以尝试将它们相乘,看看哪些应该包括,哪些应该排除。下面是它的样子:
x = 1; // Exponent
bX = b; // b^x
powers = [b]; // b^{2^0}
exps = [1]; // 2^0
while (bX <= n) {
bX *= bX; // bX = bX^2
powers += bX; // Append bX
x++;
exps += x;
}
# Overshot, now recover the bits
resultExp = 1
result = 0;
while (x > 0) {
# If including this bit doesn't overshoot, it's part of the
# representation of x.
if (resultExp * powers[x] <= n) {
resultExp *= powers[x];
result += exps[x];
}
x--;
}
return result;
x = 1;
while ((1 << x) <= n) {
x *= 2;
}
# We've overshot the high-order bit. Do a binary search to find it.
low = 0;
high = x;
while (low < high) {
mid = (low + high) / 2;
# Form a bitmask with 1s up to and including bit number mid.
# This can be done by computing 2^{m+1} - 1.
mask = (1 << (mid + 1)) - 1
# If the mask overlaps, branch higher
if (mask & n) {
low = mid + 1
}
# Otherwise, branch lower
else {
high = mid
}
}
return high - 1
还有许多我在这里没有提到的算法值得探索。有些算法将机器字分割成固定大小的块,预先计算每个块中前1位的位置,然后一次测试一个块。这些方法的运行时取决于机器字的大小,并且(据我所知)没有一种方法比我在这里概述的方法渐进地快。其他方法的工作原理是,某些处理器的指令可以立即输出数字中最高有效位的位置,或者使用浮点硬件。这些也是有趣和迷人的,一定要看看他们
另一个值得探索的领域是当您有任意精度整数时。在这里,乘法、除法、移位等的代价不是O(1),这些算法的相对代价也会改变。如果你好奇的话,这绝对值得深入探索
这里包含的代码是用伪代码编写的,因为它主要是为了说明而设计的。在实际实现中,您需要担心溢出、处理输入为负或零的情况等。仅供参考。:-)
希望这有帮助 是一个关于数学堆栈交换的类似问题,其答案为这种算法提供了伪代码。另外@jirassimok您链接的答案显示了一种算法,但已知存在更快的算法。Lior Kogan这看起来是一个关于如何计算浮点对数的很好的解释,但由于OP要求的是对数下限,因此还有其他基于离散技术的方法可能也很有用。请登录what base?@templatetypedef这就是为什么我将其作为注释而不是答案发布的原因。这正是我所要求的,我实际上想要基数2,但最终要求的是一般情况。方法1中的小修正,你必须返回x-1。@Shivraj很高兴能帮忙!还有,很好的捕获-现在已经修复了。
x = 0; # Exponent
while ((1 << x) <= n) {
x++;
}
return x - 1;
x = 1;
while ((1 << x) <= n) {
x *= 2;
}
# We've overshot the high-order bit. Do a binary search to find it.
low = 0;
high = x;
while (low < high) {
mid = (low + high) / 2;
# Form a bitmask with 1s up to and including bit number mid.
# This can be done by computing 2^{m+1} - 1.
mask = (1 << (mid + 1)) - 1
# If the mask overlaps, branch higher
if (mask & n) {
low = mid + 1
}
# Otherwise, branch lower
else {
high = mid
}
}
return high - 1
Approach Which Bases? Time Complexity Space Complexity
--------------------------------------------------------------------------
Iter. Multiplication Any O(log_b n) O(1)
Repeated Squaring Any O(log log_b n) O(log log_b n)
Zeckendorf Logarithm Any O(log log_b n) O(1)
Bitwise Multiplication 2 O(log n) O(1)
Bitwise Binary Search 2 O(log log n) O(1)
Word-Level Parallelism 2 O(1) O(1)