使用递归将基数提高到其指数-C++

Using Recursion to raise a base to its exponent - C++

本文关键字:指数 -C++ 递归      更新时间:2023-10-16

我只想写一些代码,利用函数的递归来提高基数。我知道递归不是C++中最正确的方法,但我只想稍微探索一下这个概念。该程序向用户询问基数和指数,然后用控制台输出答案。这是我写的程序:

#include <iostream>
#include <math.h>
using namespace std;
int raisingTo(int, int);
int main()
{
    int base, exponent;
    cout << "Enter base value: ";
    cin >> base;
    cout << "Enter exponent value: ";
    cin >> exponent;
    int answer = raisingTo(base, exponent);
    cout << "The answer is: " << answer << endl;
    char response;
    cin >> response;
    return 0;
}
int raisingTo(int base, int exponent)
{
    if (exponent > 0)
        return 1;
    else if (exponent = 0)
    {
        int answer = (int) pow((double)base, raisingTo(base, (exponent - 1)));
        return answer;
    }
}

有趣的是,当我运行这个程序时,它总是返回"1"的答案!有人能帮我吗?

int raisingTo(int base, unsigned int exponent)
{
    if (exponent == 0)
        return 1;
    else
        return base * raisingTo(base, exponent - 1);
}

你有3个主要问题:

  • 你不必使用pow函数
  • 要比较数字,您应该使用==,因为=是一个赋值,而不是比较
  • 您忽略了如果指数等于0,则应返回1

要使其成为一个实际的C++答案,您可以考虑将其作为模板函数,因为这应该适用于任何类型的数字。

递归实际上是一个好主意,但前提是你要利用它所能提供的好处:它可以通过从指数中分解出低数来避免一些乘法运算。

template <typename NumT>
NumT raiseTo(NumT base, unsigned exponent) {
  if (exponent == 1) return base;
  if (exponent == 0) return 1;
  if (exponent%2 == 0) { NumT ressqrt = raiseTo(base,exponent/2)
                       ; return ressqrt*ressqrt;                  }
  if (exponent%3 == 0) { NumT rescubrt = raiseTo(base,exponent/3)
                       ; return rescubrt*rescubrt*rescubrt;       }
  else return base * raiseTo(base, --exponent);
}

一个这样可以节省多少计算的例子:假设你想把一个数字提高到19。如果你使用天真的循环方法,那就是18次乘法运算。有了这个解决方案,发生的是

  • 19不可被2或3整除,因此计算b·be-1,即
  • b18。现在18可以被2整除,所以我们对be/2求平方,这就是
  • b9。其中9可被3整除,因此我们对be/3进行立方运算,即
  • b3。其中3可被3整除,因此我们对be/3进行立方运算,即
  • b1,即b

这只是1+1+2+2=6次乘法,是循环方法所需数量的1/3!但是,请注意,这并不一定意味着代码执行得更快,因为检查因素也需要一些时间。特别是,unsigneds上的%3可能并不比ints上的乘法快,所以对于NumT==int来说,它一点也不聪明。但对于更昂贵的浮点类型complex来说,是聪明的,更不用说乘法可能非常昂贵的线性代数矩阵类型了。

您的问题在于

if (exponent > 0)
    return 1;
else if (exponent = 0)

首先,您反转了条件(如果指数等于零,它应该返回),其次,您正在赋值,而不是与第二个if进行比较。

这里有一个更复杂的版本(O(lg exponent),而不是O(exponent)),它在概念上类似于leftround的版本。

int raisingTo(int base const, unsigned int const exponent, int scalar = 1)
{
    if (exponent == 0)
        return scalar;
    if (exponent & 1) scalar *= base;
    return raisingTo(base * base, exponent >> 1, scalar);
}

它还使用尾部递归,这通常会导致更好地优化机器代码。

这里有一个关于O(logn)复杂性的更清晰的解释

public int fastPower(int base , int power){
if ( power==0 )
  return 1 
else if(power %2 == 0 )
  return fastPower(base*base,power/2)
else
 return base * fastPower(base,power-1)
}

该算法遵循指数的简单规则

base^0 = 1
base^power = base*base^(power-1)
base^(2*power) = (base^2)^power

因此,在每个级别上,n的值要么是原来的一半,要么略小于n。因此,递归将进行的最深入的是1+log n

信息源