谁能解释下面的代码片段
Could anyone explain the below code snippet?
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)
将乘x
和y
,并将乘法后的值存储在结果中。
我只想知道两个"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 后,两种算法使用完全相同的乘法次数。
"算法,其中最优意味着"最少的乘法次数"。例如,从右到左和从左到右的二进制幂算法计算 x15 和x 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
设置为 power
,power
设置为 tmp * tmp
。
最终,b
除以 2 以至于它达到零,从而结束了while
循环。
该算法是所谓的"俄罗斯农民乘法"的推广,称为"平方幂"。相同的基本过程可用于幂而不是乘法,方法是对中间结果进行平方(我们在第二个if
测试中看到(而不是加倍。
时间复杂度与b
中的最高设定位成正比;如果b
中的最高设置位是位K,则循环将迭代K次。也就是说,时间复杂度与 b 的底数 2 对数成正比。
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 这两个代码片段相似,但显示的结果不同
- 如何替换此示例代码片段中已弃用的handler_type_t或 boost::asio::handler_type?
- 如果我在下面的代码片段中添加"delete[] d;",为什么我得到零?
- 我遇到了这个代码片段,不明白. 它递归检查 C++ 字符串中是否存在大写字符
- 任何人都可以解释一下我是否需要 & 在第一个代码片段中
- 提取狮身人面像文档中的C++代码片段
- 为什么此代码片段有效?如何取消引用空点?
- 无法在这个基本的Qt代码片段中找到错误,但我被告知它肯定存在?
- 这个代码片段中会发生死锁吗?为什么
- 这个代码片段中的while循环是如何工作的
- 在给定的代码中,有人可以解释一下(int i = 0; i<len; i++)count[str[i]]++的代码片段;
- 为什么我的C++代码在以下打印链表的代码片段中显示分段错误?
- 为什么这两个代码片段具有相同的效果?
- 以下代码片段的时间复杂度是多少?
- 为什么以下代码片段存在编译错误
- 如何在此代码片段中创建 begin() 指针
- 为什么这个简短的模板代码片段有效
- 为什么这个代码片段在 C 和 C++ 中生成完全不同的汇编代码?
- 我应该修复这个晦涩而优雅的C 代码片段吗?