在Java中,还有其他计算整数次幂的方法吗?
我目前使用 Math.pow(a, b)
,但它返回一个 double
,这通常需要更多的工作量,并且当您只想使用 int
时,看起来不够简洁(因为一个幂结果总是一个 int
)。
是否有像Python中的 a**b
这样简单的方法?
当指数为2的幂时,可以使用简单且快速的移位表达式 1 << 指数
例如:
22 = 1 << 2
= (int) Math.pow(2, 2)
210 = 1 << 10
= (int) Math.pow(2, 10)
对于更大的指数(超过31),请使用long类型
232 = 1L << 32
= (long) Math.pow(2, 32)
顺便提一下,在Kotlin中,你可以使用shl
代替<<
,所以
(java) 1L << 32
= 1L shl 32
(kotlin)
整数只有32位,这意味着它的最大值是2^31-1
。正如您所看到的,对于非常小的数字,您很快就会得到一个无法再由整数表示的结果。这就是为什么Math.pow
使用double
的原因。
如果您需要任意精度的整数,请使用BigInteger.pow
。但这当然不那么高效。
pow(int, int)
,那就更好了。有时候你只是想要一个整数的幂,而完全不关心浮点数。 - Petar Minchevint
时,没有什么能阻止你将溢出的值转换为 (int)
。 - Petar Minchevint
或long
输入提供*
运算符,因为对于大多数的输入,乘法都会溢出。实际上,即使加法也有约一半的时间会溢出! - BeeOnRopedouble
的最大值约为10^308,而 long
的最大值约为10^19 - 这是一个巨大的差异。 - marcotama最佳算法基于a^b的递归幂定义。
long pow (long a, int b)
{
if ( b == 0) return 1;
if ( b == 1) return a;
if (isEven( b )) return pow ( a * a, b/2); //even a=(a^2)^b/2
else return a * pow ( a * a, b/2); //odd a=a*(a^2)^b/2
}
该操作的运行时间为O(logb)。
参考资料:更多信息
isEven(b)
方法是什么?它和b % 2 == 0
一样吗? - HendraWDisEven(b)
函数 -- 意思是 ((b & 1) == 0)
-- 还有一个不必要复杂的算法! - Apostolos没有类似于a**b
这样简短的方法。
如果你想避免重复,可以使用以下简单的循环:
long result = 1;
for (int i = 1; i <= b; i++) {
result *= a;
}
如果您想使用pow
并将结果转换为整数,请按以下方式强制转换结果:int result = (int)Math.pow(a, b);
long
是64位,那么O(n)的上限就是64。这真的很糟糕吗? - Thomas Wellerimport java.util.*;
public class Power {
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
int num = 0;
int pow = 0;
int power = 0;
System.out.print("Enter number: ");
num = sc.nextInt();
System.out.print("Enter power: ");
pow = sc.nextInt();
System.out.print(power(num,pow));
}
public static int power(int a, int b)
{
int power = 1;
for(int c = 0; c < b; c++)
power *= a;
return power;
}
}
for
循环的改进:for (; b > 0; b--)
- tckmn您可以简单地使用Math.pow(a,b)
,就像之前所使用的一样,并在其前面使用(int)
进行值转换。以下可用作示例。
int x = (int) Math.pow(a,b);
其中a
和b
可以是您想要的double
或int
值。这将根据您的要求简单地将其输出转换为整数值。
3.0 ^ 1.0 = 2.999999...
,那么答案将会是错误的 2
。 - Hidde3.0
。只是举个例子,乘法的四舍五入误差2.2*3.0 = 6.0000005
而不是6.6
。 - Shubham Srivastavaint
,那么它将是精确的。如果它不适合于 int
,那么小数扩展不是你的问题,溢出才是你的问题。 - David Moles以下是一个简单的(没有检查溢出或参数有效性)实现重复平方法计算幂的算法:
/** Compute a**p, assume result fits in a 32-bit signed integer */
int pow(int a, int p)
{
int res = 1;
int i1 = 31 - Integer.numberOfLeadingZeros(p); // highest bit index
for (int i = i1; i >= 0; --i) {
res *= res;
if ((p & (1<<i)) > 0)
res *= a;
}
return res;
}
pow(int b, int k)
计算b的k次幂,并在溢出时进行包装。
checkedPow(int b, int k)
与前者相同,但在溢出时会抛出ArithmeticException
异常。checkedPow()
满足我大部分整数指数的需求,且比使用double版本和四舍五入等更为简洁和安全。在几乎所有需要幂函数的地方,溢出都是一个错误(或不可能,但如果不可能变成可能,我希望被告知)。
如果您想获得一个long
类型的结果,您可以使用相应的LongMath
方法并传递int
类型的参数。
基数是你想要进行幂运算的数字,n是指数,如果n为0,则返回1,如果n为1,则返回基数,如果条件不满足,则使用公式base*(powerN(base,n-1))。例如:使用此公式将2的n次方计算为:2(基数)*2(powerN(基数,n-1))。
public int power(int base, int n){
return n == 0 ? 1 : (n == 1 ? base : base*(power(base,n-1)));
}