Java 递归的;权力;功能
我们得到了一个用于求解递归函数的赋值,该递归函数可以使用以下规则计算数字的幂(拍摄快照): 我似乎不知道该怎么做,因为我已经试了4个小时了。 我的尝试:Java 递归的;权力;功能,java,recursion,Java,Recursion,我们得到了一个用于求解递归函数的赋值,该递归函数可以使用以下规则计算数字的幂(拍摄快照): 我似乎不知道该怎么做,因为我已经试了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) {
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的事情来平方最终结果——但这只会给我一个巨大的数字
感谢您的帮助。问题在于:
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)(@rgetman版本)
使用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
算法(因为它主要是尾部递归:
性能:
实现了三个不同的版本。这显示了基准测试。使用:
@rgetman的版本power1
此答案中建议的递归版本;以及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的测量单位是纳秒,但这些数字非常不准确,而且与副事件(如操作系统调用、缓存故障等)的关系比与实际程序运行时的关系更大。在“偶数”中在这种情况下,您可以使用递归调用来计算它,如您所做的那样传递n/2
。但是您需要将结果与自身相乘以将其平方
double value = power(x, n/2);
value *= value;
return value;
在“奇数”情况下,可以通过递归调用指数减去1
来乘以x
double value = x * (power(x, n - 1));
return value;
您需要了解递归如何在内部工作。逻辑很简单,就是将函数调用和返回值存储在堆栈中。当达到方法终止条件时,弹出值并从方法返回 你只需要这样:
public static double power(double x, int n) {
if(n == 0) {
return 1;
} else {
double value = (x * power(x, (n-1)));
return value;
}
}
在奇数情况下执行除法可能更好,因为这会显著减少调用数…@CommuSoft它可能会在此处或此处保存调用,但当我的下一个递归调用发生时,它将是偶数,并且也将在那里执行除法。因此,即使在下一个递归调用中,也会发生除法。我认为在avera中在ge的情况下,调用的数量将减少25%。事实上,没有引入额外的复杂性。请在投反对票时留下评论。我想从我的错误中吸取教训。@JunedAhson:我没有投反对票,但这种方法的问题是,算法在线性时间内运行,具有强大的能力和能力(如果没有优化的话),以一个巨大的堆栈返回。@CommuSoft谢谢!我试图提供一个简单的解决方案,而不是优化的解决方案。此解决方案是针对提问者的,而不是针对超级编码者。问题要求不涉及算法的复杂性。我亲爱的投票人/优化编码者。此解决方案不适合您。很抱歉冒犯您。不确定哪一个答案我应该接受:(P.S-我有一个脑屁。你能解释一下功率(x*x,n/2)是如何工作的吗?我不明白它是如何工作的,即使你没有给出正确的答案。
public static double power(double x, int n) {
if(n == 0) {
return 1;
} else {
double value = (x * power(x, (n-1)));
return value;
}
}