谁能解释下面的代码片段

Could anyone explain the below code snippet?

本文关键字:代码 片段 能解释      更新时间:2023-10-16
void dec_exp(Decimal *result, const Decimal *a, unsigned int b)
    {
        Decimal tmp, power = *a;
        dec_parse(result, "1");
        while (b)
        {
            if (b & 1)
            {
                tmp = *result;
                dec_mul(result, &tmp, &power);
            }
            if (b >>= 1)
            {
                tmp = power;
                dec_mul(&power, &tmp, &tmp);
            }
    }
}

其中Decimal是包含十进制值的结构变量,它是长度和小数点所在的位置。

函数中传递的参数:a 是基值,b是幂。计算后result将存储值 a^b。

dec_parse(Decimal &x,string y)会将y解析为十进制并提取小数点的位置等信息,修剪前导和尾随零,并将字符串转换为Decimal结构变量。

dec_mul(Decimal result, Decimal &x, Decimal &y)将乘xy,并将乘法后的值存储在结果中。

我只想知道两个"if 条件"在 while 循环中是如何工作的,while 循环何时终止以及代码片段的时间复杂度。

这是

b是非负整数的特殊情况下计算(*a) b

变量result被初始化为1(注意a 0是所有a的1(,power被初始化为a的内容。每次通过循环时,如果b是奇数,则result乘以 power(第一个if(。第二个if右移b一位(即除以 2(,如果这仍然是正数,则平方power 。换句话说,power包含逐渐增大的值,(*a) 2n

这是一种相当有效且易于实现(但不是最佳(的计算b 算法。最佳算法是NP硬的,并且(可能(需要大量内存。此算法易于编码,并且需要最少的内存。

忽略多余的乘以 1,此算法最适合b =0 到 b =14。它在 a 15 中是次优的。该算法计算为 a 15 a * a 2* a 4* a 8 或 6 次乘法。最佳计算(调用decimal次数最少的计算(是 a 3= a * a * a ; a 15= a 3*(( a 3(2(2,或五个乘法。


此算法的另一个名称是从右到左的二进制幂。之所以这样称呼,是因为它从b的最右边位(一位(开始,并逐渐处理b中更重要的位。换句话说,它从右到左工作。从左到右的二进制幂从b的最有效位开始,并逐渐处理不太重要的b位。在消除多余的乘法 1 后,两种算法使用完全相同的乘法次数。

这不是"最优

"算法,其中最优意味着"最少的乘法次数"。例如,从右到左和从左到右的二进制幂算法计算 x15x 31

    x 15 = x*x 2*x 4*x 8 = ((x 2*x(2*x(
  • 2*x(分别为从右到左和从左到右(
  • x 31 = x*x 2*x 4*x 8*x 16 = (((x 2*x(2*
  • x(2*x(2*x

但是由于 15=(4+1(*3, 31=15*2+1=((4+1(*3(*2+1 和 31=7*4+3=(3*2+1(*4+3,我们也可以写:

    x
  • 15 = (x4*x(3
  • x
  • 31 = ((x4*x(3(2*x
  • x
  • 31 = (((x 3(2*x(4(*x3

所有这些都需要比二进制幂少一次乘法。(最终表达式需要缓存中间结果 x3,以避免计算两次。我不知道我对 x31 的表达式是否是最佳的。即使对于较小的数字,也很难找到最佳表达式。您必须查看表示 xn 的所有不同方式,请记住,常见的中间结果只需要计算一次。如上所述,这是NP硬的。在实践中,二进制幂虽然不是最优的,但已经足够好了。

>b & 1测试b是否为奇数。如果是,则result设置为 tmp * power

b >>= 1 将 b 除以 2。如果结果不为零,则tmp设置为 powerpower设置为 tmp * tmp

最终,b除以 2 以至于它达到零,从而结束了while循环。

该算法是所谓的"俄罗斯农民乘法"的推广,称为"平方幂"。相同的基本过程可用于幂而不是乘法,方法是对中间结果进行平方(我们在第二个if测试中看到(而不是加倍。

时间复杂度与b中的最高设定位成正比;如果b中的最高设置位是位K,则循环将迭代K次。也就是说,时间复杂度与 b 的底数 2 对数成正比。