簡體   English   中英

遞歸冪函數:方法

[英]Recursive power function: approach

我現在編程了一段時間(初學者),遞歸函數對我來說是一個有點抽象的概念。 我不會說我卡住了,程序運行良好,我只是想知道是否可以在代碼中沒有 pow 函數的情況下編寫函數本身(但仍然完全按照問題的建議進行操作)

問題: http : //prntscr.com/30hxg9

我的解決方案:

#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);
}

我試過這樣做: power(power(x, n - 1), 2); 但是執行失敗了,我仍在回溯原因。

在重寫函數時,不要忽視遞歸在這種情況下的主要好處,即減少所需的乘法運算次數。 例如,如果 n = 8,那么將 x * x 計算為 val1,然后將 val1 * val1 計算為 val2,將最終答案計算為 val2 * val2(3 次乘法)比計算 x * x * x * 要高效得多x * x * x * x * x(7 次乘法)。

這種差異對於小整數來說是微不足道的,但是如果您將此操作置於大循環中,或者如果您用非常大的數字表示或可能是巨大的矩陣替換整數,則很重要。

這是在不消除遞歸效率的情況下擺脫 pow() 函數的一種方法:

#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);
}

編碼:

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);
}

不起作用,因為當 n 是偶數時,用 n = 2 調用冪,這是偶數,然后用 n = 2 調用冪,這是偶數,然后用 n = 2 調用冪......直到......堆棧溢出!

簡單的解決方案:

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);
}

對於冪函數(假設是 x 的 n 次冪),您有兩種情況:

exponent=0
exponent=n

對於第一種情況,您只需要返回 1。在另一種情況下,您需要返回 x 的 n 減 1 次方。 在那里,您只是遞歸地使用了該函數。

int power(int x, n)
{
    if(n == 0) return 1;
    else return x * power(x, n-1);
}
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;
}

這適用於正值、負值和 0 值

簡單但做 n 次乘法。 上面的例子效率更高,因為它們在一次迭代中將兩個操作組合在一起

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

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

這是ruby中的一個解決方案,它也適用於負指數

# 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)

我的 C++ 方法僅適用於非負數。

#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);
}
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;
    }
}

您想避免使用pow() ,對嗎? 因此,您改用power() ,導致在參數列表中進行遞歸調用 這導致了分段錯誤

首先,讓我們了解問題的原因。 我對算法進行了筆和紙運行,結果非常有趣。 事實證明,對於 x 和 n 的任何值,經過一定次數的遞歸后,總會得到power(1, 2) 這也意味着, power(1, 2)也導致power (1, 2)一定數目的遞歸后。 因此, power()中的這個power()導致無限遞歸,從而導致堆棧溢出

現在,回答你的問題。 是的,這可以在不使用 pow() 的情況下完成,因為 pow(a, 2) 可以簡單地寫為 a*a。 因此,這里對您的代碼稍作修改:

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);
}

但是,為什么要這樣做呢? 更有效的方法如下。

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);
}

這減少了所需的遞歸次數,使代碼更節省時間和空間。 希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM