【问题标题】:exponentiation in Data Structures and Algorithm Analysis in C数据结构中的幂运算和 C 中的算法分析
【发布时间】:2017-08-17 03:51:26
【问题描述】:

在第 2 章中提到求幂时,作者提到

"所需的乘法次数显然最多为 2 log n(底数为 2),因为在 最多需要两次乘法(如果 n 是奇数)才能将问题减半。再次,可以写出递推公式并求解。”

代码如下:

int pow( int x, unsigned int n)
{
/*1*/ if( n == 0 )
/*2*/ return 1;
/*1*/ if( n == 1 )
/*4*/ return x;
/*5*/ if( even( n ) )
/*6*/ return( pow( x*x, n/2 ) );
else
/*7*/ return( pow( x*x, n/2 ) * x );
}

: 正如作者所说,

2^16 最多需要 8 次乘法

2^15 ... 7 ...

2^14 ... 7 ...

2^13 ... 7 ...

2^12 ... 7 ...

其实我是按照代码执行的:

2^16 .... 4 ...

2^15 .... 6 ...

2^14 ... 5 ...

2^13 ... 5 ...

2^12 ... 4 ...

那么,是不是哪里出错了?

【问题讨论】:

  • 16 的 4 倍除以 2。需要 4 次迭代。所以这本书可能是错的。
  • 他说最多是一个上限估计。您所有的数字都较低,因此他的上限成立。 (但可能会改进)
  • 不确定您的投诉内容。他说乘法的数量是<= 2 log n(这就是“最多”的意思)。你的情况n = 2^16的乘法次数是4,根据作者的说法,确实是'
  • 如果我说'任意人的腿数最多 7',我说的是真的。
  • @KamiKaze 那么如何获得上限2 log n

标签: c algorithm exponentiation


【解决方案1】:

没有矛盾或错误——这本书给出了一个上限,而你正在查看乘法的确切数量。

乘法的确切数量(对于 n>0)是 floor(log_2(n)) + bitcount(n) - 1。这只是通过检查代码 - 偶数情况(执行一次乘法)对应于 0输入中的位,奇数情况(执行额外的乘法)对应于输入中的 1 位,代码在到达最高位时停止。

书上说 2*log_2(n) 是乘法次数的上限。这与确切的公式一致:floor(log_2(n))

从精确的公式可以看出,n的bitcount越低,上限越差。最坏的情况是 n 是 2 的幂:那么将执行 log_2(n) 乘法,并且上限偏离 2 倍。最好的情况是 n 小于 1 的幂2:那么上限将仅偏离 1。这与您的经验结果表相匹配。

【讨论】:

  • 我喜欢这个分析,因为它很容易看出最坏的情况(乘法次数)是 n 小于 2 的幂。它花了我花了几分钟才意识到您考虑了预测乘法数和实际乘法数之间的“最坏情况”和“最佳情况”一致,而我考虑了“最坏情况”和“最佳情况” case" 表示乘法的次数。
  • 完美地让我清楚。但是 和上限相差 2 倍 是什么意思?有点困惑。
  • 我的意思是在 n 是 2 的幂的情况下,上限是 2log_2(n),乘法的确切数量是 log_2(n)。上限是确切数字的 2 倍——所以它是关闭/不正确的 2 倍。我注意到我在这里的答案中不小心省略了“of”这个词,所以也许这就是令人困惑的地方——但我现在修复了.
【解决方案2】:

x^n 最多需要 2 log n 次乘法,因为可能有 n/2 在每次迭代中都是奇数。例如:

pow(2, 15) --> pow(2 * 2, 7) * 2
           --> pow(4 * 4, 3) * 4 * 2
           --> pow(16 * 16, 1) * 16 * 4 * 2

这是六次乘法(每个函数调用两次乘法); 2 * log(15) ~= 7.8。所以满足上限。最好的情况是 n 2 的幂,它只需要 log n 次乘法。

为了计算复杂度,考虑这个算法将n减少了一半k次,直到n在1到2之间;也就是说,我们有:

1 ≤ n2k

所以:

2k ≤ n k+1
⇒ k ≤ log n ⇒ (log n) - 1

因此,该算法需要 log n 步,由于最坏的情况是每步两次乘法,因此最多需要 2 log n 次乘法。

【讨论】:

  • 如你所说 (log n) - 1 ,最多 2 log n 次乘法。以及是否是乘法超过 ** 2( (log n) - 1)?所以2^12的乘法应该小于等于7且大于5。
  • @Jedore-- 对于 2^122.58 ,但是 k( steps) 是一个整数,所以 k = 3。乘法的次数最多为 6 次,因为每步最多有 2 次乘法。在@Paul Hankin之后,bitcount(12) = 2,所以实际的乘法次数是⌊log 12 + 1⌋ = 4。您可以通过对pow(2, 12) 的评估来验证这是实际的乘法次数。
最近更新 更多