Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 这个乘法算法的时间复杂度是多少?_C_Performance_Complexity Theory_Big O - Fatal编程技术网

C 这个乘法算法的时间复杂度是多少?

C 这个乘法算法的时间复杂度是多少?,c,performance,complexity-theory,big-o,C,Performance,Complexity Theory,Big O,对于经典的面试问题“在没有乘法运算符的情况下如何执行整数乘法?”,最简单的答案当然是以下C语言中的线性时间算法: int mult(int multiplicand, int multiplier) { for (int i = 1; i < multiplier; i++) { multiplicand += multiplicand; } return multiplicand; } int mult(int被乘数,int乘数) {

对于经典的面试问题“在没有乘法运算符的情况下如何执行整数乘法?”,最简单的答案当然是以下C语言中的线性时间算法:

int mult(int multiplicand, int multiplier)
{
    for (int i = 1; i < multiplier; i++)
    {
        multiplicand += multiplicand;
    }

    return multiplicand;
}
int mult(int被乘数,int乘数)
{
对于(int i=1;i被乘数+=被乘数;
}
返回被乘数;
}
当然,还有一种更快的算法。如果我们利用位向左移位等于移位位数的幂乘以2的特性,我们可以将位向上移位到最接近的幂2,并使用我们以前的算法从那里相加。因此,我们的代码现在看起来像这样:

#include <math.h>

int log2( double n )
{
    return log(n) / log(2);
}

int mult(int multiplicand, int multiplier)
{
    int nearest_power = 2 ^ (floor(log2(multiplier)));
    multiplicand << nearest_power;
    for (int i = nearest_power; i < multiplier; i++)
    {
        multiplicand += multiplicand;
    }

    return multiplicand;
}
#包括
整数log2(双n)
{
返回日志(n)/log(2);
}
int mult(int被乘数,int乘数)
{
整数幂=2^(下限(对数2(乘数));
被乘数Edit

让我们看看第二个发布的算法,首先是:

int nearest_power = 2 ^ (floor(log2(multiplier)));
我相信计算log2,相当令人高兴的是,是O(log2(乘数))

然后最近的_幂到达区间[multiplier/2 to multiplier],其大小为multiplier/2。这与查找正数的最高设置位相同

所以
循环的
是O(乘数/2),常数是1/2,所以是O(n)

平均来说,它是间隔的一半,是O(乘数/4)。但这只是常数1/4*n,所以它仍然是O(n),常数更小,但仍然是O(n)

更快的算法

我们的直觉是,我们可以在n步中乘以一个n位数

在二进制中,这是使用1位移位、1位测试和二进制加法来构造整个答案。每个操作都是O(1)。这是长乘法,一次一位

如果我们对n使用O(1)运算,一个x位数字,它是O(log2(n))或O(x),其中x是数字中的位数

这是一个O(log2(n))算法:

int mult(int multiplicand, int multiplier) {
    int product = 0;

    while (multiplier) {
        if (multiplier & 1) product += multiplicand;
        multiplicand <<= 1;
        multiplier >>= 1;
    }

    return product;
}
int mult(int被乘数,int乘数){
int乘积=0;
while(乘数){
如果(乘数&1)乘积+=被乘数;
被乘数=1;
}
退货产品;
}
这本质上就是我们如何做长乘法

当然,明智的做法是使用较小的数字作为乘数


这只适用于正值,但通过测试和记住输入的符号,对正值进行操作,然后调整符号,它适用于所有数字。

可以大到
乘法器的一半,当它趋于无穷大时,常数
0.5
就可以了esn无所谓(更不用说我们去掉了大O中的常量)。因此循环是
O(乘法器)
。我不确定位移位

编辑:我更详细地了解了位移位。正如gbulmer所说,它可以是
O(n)
,其中
n
是移位的位数。但是,在某些体系结构上,它也可以是
O(1)
。请参阅:


然而,在这种情况下,这并不重要!
n>log2(n)
对于所有有效的
n
。因此我们有
O(n)+O(乘数)
,它是
O(2*乘数)
的一个子集,由于上述关系,因此整个算法是
O(乘数)

查找最近幂的目的是使函数运行时接近运行时O(1)。当2^最近幂与添加的结果非常接近时,会发生这种情况

在幕后,整个“2的幂”是通过位移位完成的

因此,为了回答您的问题,您的代码的第二个版本仍然是更糟糕的线性时间:O(乘数)。

你的答案O(n-2^(floor(log2(n)))也没有错;它非常精确,可能很难在你的头脑中快速找到边界。

multipliand+=multipliand;Fixed-谢谢你指出这一点。你的第一个算法不是乘法算法,但结果是
multipliant*pow(2,multiplier)
,不是吗?啊,一个接一个的错误…谢谢你指出,修复了。@HerroRygar-值得注意的是,这两个错误只适用于正乘法器(我的位移位和加法也有这个问题)。这也不是
log2()
和移位乘法一样昂贵?你有这个算法的一个例子的链接吗?当然,虽然我认为你可能了解一些东西。=@HerroRygar-我已经发布了算法所以,我现在看到的只是一个最佳情况常数时间,平均情况和最坏情况线性?你可以看看最佳、平均和最坏情况;你可以n还可以查看大O等符号给出的渐近界。这取决于你想看到什么。查看维基百科上的大O符号、小O符号、θ符号以及大小ω。大O是最常用的一种:问题中用于推导2的最近幂的技术比O(log2(n))差,所以O(1)然后是一个O(n)加法-(x-1和x/2)之间的距离是x/4,这仍然是O(x),但是如果有一个较小的连续位移位是O(log2(乘法器))或O(log2(min(乘法器,被乘数)),请看我的回答:1位移位是O(1)(在我所知道的所有现代机器上),IMHO,对于这个问题,n位移位可能是O(1)并不相关。乘法需要n个1位移位,其中n实际上是最高的设定位,为简单起见,它是乘法器中的位数。总结:任意数量的移位可能是O(1)并不重要,因为我们只需要1位移位,但我们需要其中的n位乘以n位乘法器,因为我们需要能够在每个移位后进行加法。