Recursive power function: approach

寵の児 提交于 2020-01-11 07:02:23

问题


I'm programming for a while now(beginner), and recursive functions are a somewhat abstract concept for me. I would not say I'm stuck, program works fine, I'm just wondering if the function itself could be written without the pow function in the code (but still doing exactly what the problem suggests)

Problem: http://prntscr.com/30hxg9

My solution:

#include<stdio.h>
#include<math.h>

int power(int, int);

int main(void)
{
    int x, n;
    printf("Enter a number and power you wish to raise it to: ");
    scanf_s("%d %d", &x, &n);
    printf("Result: %d\n", power(n, x));
    return 0;
}

int power(int x, int n)
{
    if (n == 0) return 1;
    if (n % 2 == 0) return pow(power(x, n / 2), 2);
    else return x * power(x, n - 1);
}

I've tried doing this: power(power(x, n - 1), 2); but execution failed, and I'm still backtracking why.


回答1:


When rewriting your function, don't lose sight of the main benefit of recursion in this case, which is to reduce the number of multiplication operations required. For example, if n = 8, then it is much more efficient to compute x * x as val1, then val1 * val1 as val2, and the final answer as val2 * val2 (3 multiplications) than to compute x * x * x * x * x * x * x * x (7 multiplications).

This difference is trivial for small integers but matters if you put this operation inside a big loop, or if you replace the integers with very large number representations or maybe ginormous matrices.

Here's one way to get rid of the pow() function without getting rid of the recursion efficiency:

#include<stdio.h>
#include<math.h>

int power(int, int);

int main(void)
{
    int x, n;
    printf("Enter a number and power you wish to raise it to: ");
    scanf_s("%d %d", &x, &n);
    printf("Result: %d\n", power(x, n));
    return 0;
}

int power(int x, int n)
{
    int m;
    if (n == 0) return 1;
    if (n % 2 == 0) {
        m = power(x, n / 2);
        return m * m;
    } else return x * power(x, n - 1);
}



回答2:


The code:

int power(int x, int n)
{
    if (n == 0) return 1;
    if (n % 2 == 0) return power(power(x, n / 2), 2);
    else return x * power(x, n - 1);
}

does not work because when n is even power is called with n = 2 which is even and then power is called with n = 2 which is even and then power is called with n = 2 ... until ... stack overflow!

Simple solution:

int power(int x, int n)
{
    if (n == 0) return 1;
    if (n % 2 == 0) {
        if (n == 2) return x * x;
        return power(power(x, n / 2), 2);
    }
    else return x * power(x, n - 1);
}



回答3:


For the power function (let's say, x to the nth power) you have two cases:

exponent=0
exponent=n

For the first case, you only need to return 1. In the other case, you need to return x to the power of n minus one. There, you only used the function recursively.

int power(int x, n)
{
    if(n == 0) return 1;
    else return x * power(x, n-1);
}



回答4:


double result = 1;
int count = 1;

public double power(double baseval, double exponent) {
  if (count <= Math.Abs(exponent)){
    count++;
    result *= exponent<0 ?1/baseval:baseval;
    power(baseval, exponent);
  }
  return result;
}

This works with positive, negative, and 0 value




回答5:


Simple but does n number of multiplications. Above examples are more efficient because they group two operations in one iteration

int power(int x, int n)
{
    if (n == 0) return 1;

    return x * power(x, n-1);
}



回答6:


Here is a solution in ruby which works for negative exponents as well

# for calculating power we just need to do base * base^(exponent-1) for ex:
# 3^4 = 3 * 3^3
# 3^3 = 3 * 3^2
# 3^2 = 3 * 3^1
# 3^1 = 3 * 3^0
# 3^0 = 1

# ---------------------------------------------------------------------------
# OPTIMIZATION WHEN EXPONENT IS EVEN
# 3^4 = 3^2 * 3^2
# 3^2 = 3^1 * 3^1
# 3^1 = 3^0
# 3^0 = 1
# ---------------------------------------------------------------------------

def power(base, exponent)
  if(exponent.zero?)
    return 1
  end
  if(exponent % 2 == 0)
    result = power(base, exponent/2)
    result = result * result
  else
    result = base * power(base, exponent.abs-1)
  end

  # for handling negative exponent
  if exponent < 0
    1.0/result
  else
    result
  end
end

# test cases
puts power(3, 4)
puts power(2, 3)
puts power(0, 0)
puts power(-2, 3)
puts power(2, -3)
puts power(2, -1)
puts power(2, 0)
puts power(0, 2)



回答7:


My approach with C++, works only with non-negative numbers.

#include <iostream>
using namespace std;

long long  power(long long x, long long y) {
if (y == 0) {
    return  1;
}
else {
    y--;
    return x*power(x,y);
 }
}
main() {
long long n, x;
cin >> n >> x;
cout << power(n,x);
}



回答8:


int pow(int a, int n) {
    if(n == 0) return 1;
    if(n == 1) return a;
    int x = pow(a, n/2);
    if(n%2 == 0) {
        return x*x;
    }
    else {
        return a*x*x;
    }
}



回答9:


You want to avoid using pow(), right? So you used power() instead, leading to a recursive call within the argument list. This led to a segmentation fault.

First of all, let us understand the cause of the problem. I did a pen and paper run of the algorithm and the result is pretty interesting. It turns out that for any values of x and n, after a certain number of recursions one always ends up getting power(1, 2). This also means that power(1, 2) also leads to power (1, 2) after a certain number of recursions. Thus, this power() within a power() leads to an infinite recursion and thus the stack overflow.

Now, to your question. Yes, this can be done without using pow() because pow(a, 2) can simply be written as a*a. So, here is a slight modification to your code:

int power(int x, int n)
{
    if (n == 0) return 1;
    if (n % 2 == 0) return power(x, n / 2) * power(x, n / 2);
    else return x * power(x, n - 1);
}

But then, why do it this way? A more efficient way would be as follows.

int power(int x, int n)
{
    if (n == 0) return 1;
    if (n % 2 == 0) return power(x * x, n / 2);
    else return x * power(x * x, n / 2);
}

This reduces the number of recursions needed, making the code more time and space efficient. Hope this helps!



来源:https://stackoverflow.com/questions/22389184/recursive-power-function-approach

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!