[英]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.