Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对于两个数字,如何测试一个是否是另一个的整数幂?_Java_Algorithm_Logarithm_Exponent - Fatal编程技术网

Java 对于两个数字,如何测试一个是否是另一个的整数幂?

Java 对于两个数字,如何测试一个是否是另一个的整数幂?,java,algorithm,logarithm,exponent,Java,Algorithm,Logarithm,Exponent,对于整数x、y和n,(仅给出x和y)测试xn=y?如果x=8,y=512,那么n=3,这是真的。但是如果x=8,y=500,n必须在2.98左右(不是整数),因此语句的计算结果为false。使用对数是做这个测试的最好方法吗 提供了一些解决方案: int n=y;而(n

对于整数x、y和n,(仅给出x和y)测试xn=y?如果x=8,y=512,那么n=3,这是真的。但是如果x=8,y=500,n必须在2.98左右(不是整数),因此语句的计算结果为false。使用对数是做这个测试的最好方法吗

提供了一些解决方案:

int n=y;而(n

while (x%y == 0)  x = x / y
return x == 1
对数法(这是我的版本):

对数(y,x)=对数x y


哪种方法评估速度更快,尤其是对于大数字?

如果不进行基准测试,只看发生了什么,这一种应该是最快的

int n = y; while(n < x) n *= y; return n == x;
这是一个除法和一个模(本质上是第二个除法),所以它做了两倍的功,但是它可以更早地退出循环,所以它可能会赢

return ((log(y, x) % 1) == 0)

这使用了本质上是邪恶的浮点运算(尽管浮点运算在现代CPU芯片中变得更好更快)。然而,当你需要知道它是完整的还是不完整的时候,你做测试的模块是偶数还是奇数。

如果不进行基准测试,只看发生了什么,这个应该是最快的

int n = y; while(n < x) n *= y; return n == x;
这是一个除法和一个模(本质上是第二个除法),所以它做了两倍的功,但是它可以更早地退出循环,所以它可能会赢

return ((log(y, x) % 1) == 0)
这使用了本质上是邪恶的浮点运算(尽管浮点运算在现代CPU芯片中变得更好更快)。然而,当你需要知道它是完整的还是不完整的时候,你测试它的模数是偶数还是奇数。

如果存在一个b和e,其中b^e=n,那么数字n是一个完美的幂。例如,216=6^3=2^3*3^3是一种完美的力量,但72=2^3*3^2不是。如果数字n是完美幂,则指数e必须小于log2n,因为如果e大于,则2^e将大于n。此外,只需要测试素数*e*s,因为如果数字是复合指数的完美幂,那么它也将是复合分量素数因子的完美幂;例如,2^15=32768=32^3=8^5是一个完美的立方根,也是一个完美的第五根

我在我的博客上有一个数字。如果存在一个b^e=n的b和e,那么n是一个完美的幂。例如,216=6^3=2^3*3^3是一种完美的力量,但72=2^3*3^2不是。如果数字n是完美幂,则指数e必须小于log2n,因为如果e大于,则2^e将大于n。此外,只需要测试素数*e*s,因为如果数字是复合指数的完美幂,那么它也将是复合分量素数因子的完美幂;例如,2^15=32768=32^3=8^5是一个完美的立方根,也是一个完美的第五根


我在我的博客上有一个测试。

对于大量用户,日志可能会更快,但您应该对其进行基准测试。这将涉及到转换为双重和反向,这可能是一个问题

我认为这可能是一个更好的解决方案:

long y = 512;
long x = 8;
if (x <= 1) return false;
while (y>1) {
    // Find maximum x^(2^n) <= y
    long xp = x;   // x to some maximum power
    long xp2;      // experimental value of xp
    while ((xp2 = xp*xp) <= y)
      xp = xp2;
    if (y%xp != 0) return false;  // reject
    y /= xp;
}
return y == 1;
长y=512;
长x=8;
if(x1){

//查找最大x^(2^n)对于较大的数字,日志可能会更快,但您应该对其进行基准测试。这将涉及到转换为double和back,这可能是一个问题

我认为这可能是一个更好的解决方案:

long y = 512;
long x = 8;
if (x <= 1) return false;
while (y>1) {
    // Find maximum x^(2^n) <= y
    long xp = x;   // x to some maximum power
    long xp2;      // experimental value of xp
    while ((xp2 = xp*xp) <= y)
      xp = xp2;
    if (y%xp != 0) return false;  // reject
    y /= xp;
}
return y == 1;
长y=512;
长x=8;
if(x1){

//查找最大值x^(2^n)对数方法需要更加小心,因为由于使用浮点近似,对数函数有少量不精确性。例如310=59049,但是:

log(59049, 3)
   ===> 9.999999999999998
是否可以对此进行补偿(通过检查答案是否与最接近的整数“足够接近”)取决于x和y的范围。如果y小于232,则我认为对数与整数成比例的最接近值(真实答案不是整数)是:

因此,选择一个比这个小的ε,您可以放心地使用对数方法:

n = log(y, x);
e = round(n);
if (abs(1 - n / e) < epsilon) {
    /* y == x to the power of e */
} else {
    /* y not a power of x */
}

因此,对于足够大的y,您不能依赖于对数:您需要在检查之后显式执行幂运算。

对数方法需要更加小心,因为由于使用浮点近似,对数函数有少量的不精确性。例如310=59049,但是:

log(59049, 3)
   ===> 9.999999999999998
是否可以对此进行补偿(通过检查答案是否与最接近的整数“足够接近”)取决于x和y的范围。如果y小于232,则我认为对数与整数成比例的最接近值(真实答案不是整数)是:

因此,选择一个比这个小的ε,您可以放心地使用对数方法:

n = log(y, x);
e = round(n);
if (abs(1 - n / e) < epsilon) {
    /* y == x to the power of e */
} else {
    /* y not a power of x */
}

因此,对于足够大的y,您不能依赖对数:您需要在检查之后显式地执行求幂运算。

对于合理的小输入,我相当确定您的第三种方法将工作得最好。(不过,您需要更加小心地检查完整性。)

值得思考的是:

  • 您可以非常快速地计算
    x
    的幂,即
    sqrt(y)
    的幂(即O(M(logy))时间),然后根据该幂(O(M(logy)logy)时间)进行mod,以得到大小为一半的两个子问题

  • 你可以使用相当差的对数近似值来获得
    n
    上相当严格的界限。如果我知道一个整数在
    log_x(y)
    的常数范围内,那么我只需要检查
    x
    的常数次幂。这些检查使用“平方和乘法技术”完成得最快爱德华·福克的回答就是例证

  • 即使在
    n
    上有一个相当宽的范围,你也可以使用算术模对一个中等大小的随机素数进行运算,以大大缩小候选
    n
    的范围。应该可以使用算术模对几个中等大小的随机素数进行运算,并结合中国剩余定理来缩小可能的