我们有一个赋值来解决递归函数,该函数可以使用以下规则计算数字的幂(拍摄快照):
http://i.imgur.com/sRoQJ1j.png
我似乎无法做到这一点,因为我在过去的4个小时里一直在努力。 我的尝试:
public static double power(double x, int n) {
if(n == 0) {
return 1;
}
// x^n = ( x^n/2 )^ 2 if n > 0 and n is even
if(n % 2 == 0) {
double value = ((x * power(x, n/2)) * x);
return value;
} else {
double value = x * ((x * power(x, n/2)) * x);
return value;
}
}
我相信当我将x与递归函数相乘时我做错了,而我应该乘以x(幂= x * x * .... x(n))......
我也可以在本声明中看到:
double value = ((x * power(x, n/2)) * x);
这是错误的,因为我没有对值进行平方,而只是将其与x相乘。我认为我需要先将它存储在一个变量中,然后执行类似value * value的操作来平衡最终结果 - 但这只会给我一个巨大的数字。
感谢任何帮助,谢谢。
答案 0 :(得分:1)
问题出在这句话中:
if(n % 2 == 0) {
double value = ((x * power(x, n/2)) * x);
return value;
它在语法上(括号不匹配)在语义上(更深的递归,不正确)。
应替换为:
if(n % 2 == 0) {
double value = power(x*x, n/2);
return value;
原因是:
x ^(2 * k)=(x ^ 2)^ k
这几乎就是代码中实现的内容。因为我们知道n
是偶数,所以有一个k = n/2
,以便上述等式成立。
与奇怪的情况相同:
else {
double value = x * power(x*x, n/2);
return value;
这是因为:
x ^(2 * k + 1)= x * x ^(2 * k)(@rgettman的版本)
使用k = (n-1)/2
,可以进一步优化:
x ^(2 * k + 1)= x * x ^(2 * k)= x *(x ^ 2)^ k(我们的版本)
您可以进一步优化:
public static double power(double x, int n) {
if(n == 0) {
return 1;
}
double xb = x*x;
if((n&0x01) == 0x00) {
return power(xb,n>>>0x01);
} else {
return x*power(xb,n>>>0x01);
}
}
或者,您可以将递归方面转换为while
算法(因为它主要是尾递归:
public static double power(double x, int n) {
double s = 1.0d;
while(n != 0) {
if((n&0x01) != 0x00) {
s *= x;
}
n >>>= 0x01;
x *= x;
}
return s;
}
<强>性能强>:
实施了三个不同的版本。这个jdoodle显示了基准测试。用:
power1
@rgettman的版本; power2
此答案中提出的递归版本;和power3
非递归版本。如果有人将L
设置为10'000'000
(因此计算所有权力从0
到L
),则一次运行会导致:
L = 10M L=20M
power1: 1s 630 018 699 3s 276 492 791
power2: 1s 396 461 817 2s 944 427 704
power3: 0s 803 645 986 2s 453 738 241
不要认真对待逗号之后的数字。尽管Java以纳秒为单位测量,但这些数字非常不准确,并且与副事件(如OS调用,缓存故障......等)有关,而不是与实际程序运行时有关。
答案 1 :(得分:1)
在“偶数”情况下,您可以使用递归调用计算它,并按照您的方式传递n/2
。但是你需要将结果与自身相乘以对其进行平方。
double value = power(x, n/2);
value *= value;
return value;
在“奇数”情况下,您可以将x
乘以指数减去1
的递归调用。
double value = x * (power(x, n - 1));
return value;
答案 2 :(得分:0)
您需要了解递归在内部的工作原理。逻辑很简单,就是将函数调用和返回值存储在堆栈中。达到方法终止条件时,弹出值并从方法返回。
你只需要这个:
public static double power(double x, int n) {
if(n == 0) {
return 1;
} else {
double value = (x * power(x, (n-1)));
return value;
}
}