英文:
Fixing the performance time of algorithm
问题
以下是翻译后的代码部分:
/**
*
* 一个用于计算整数的完全幂的实用类
*/
public class PerfectPower {
public static void main(String[] args) {
new TimeExec(new Runnable() {
public void run() {
System.out.println("17的完全幂是 " + getPerfectPower(17));
}
}, "获取17的完全幂", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("625的完全幂是 " + getPerfectPower(625));
}
}, "获取625的完全幂", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("1024的完全幂是 " + getPerfectPower(1024));
}
}, "获取1024的完全幂", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("10000的完全幂是 " + getPerfectPower(10000));
}
}, "获取10000的完全幂", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("1073741824的完全幂是 " + getPerfectPower(1073741824));
}
}, "获取1073741824的完全幂", System.out).start();
}
/**
* 获取一个数的完全幂。
* @param x 要计算完全幂的数。
*/
public static int getPerfectPower(int x) {
int largestP = 1;
for (int b = 1; b < x; b++) {
for (int p = 1; p < x; p++) {
if (Math.pow(b,p) == x) {
largestP = p;
}
}
}
return largestP;
}
}
以下是对应的输出部分:
17的完全幂是 1
TimeExec: 获取17的完全幂: 0.001s
625的完全幂是 2
TimeExec: 获取625的完全幂: 0.026s
1024的完全幂是 2
TimeExec: 获取1024的完全幂: 0.052s
10000的完全幂是 2
TimeExec: 获取10000的完全幂: 1.9s
1073741824的完全幂是 X
TimeExec: 获取1073741824的完全幂: XX.XXXs
英文:
The following program is created to to calculate the perfect power of numbers
The end result is to have the Perfect Power complete all test cases in under .01s of elapsed execution time.
Currently the program end result time performance is at about 2+secs for 10,000 and the one for 1073741824 takes much much longer. Need assistance to help lower the time for all perfect-powers to be .01 seconds and less.
Below is the program code:
/**
*
* A utlity class to calculate the perfect power of an integer
*/
public class PerfectPower {
public static void main(String[] args) {
new TimeExec(new Runnable() {
public void run() {
System.out.println("Perfect Power of 17 is " + getPerfectPower(17));
}
}, "Get Perfect Power of 17", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("Perfect Power of 625 is " + getPerfectPower(625));
}
}, "Get Perfect Power of 625", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("Perfect Power of 1024 is " + getPerfectPower(1024));
}
}, "Get Perfect Power of 1024", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("Perfect Power of 10000 is " + getPerfectPower(10000));
}
}, "Get Perfect Power of 10000", System.out).start();
new TimeExec(new Runnable() {
public void run() {
System.out.println("Perfect Power of 1073741824 is " + getPerfectPower(1073741824));
}
}, "Get Perfect Power of 1073741824", System.out).start();
}
/**
* Get the perfect power for a number.
* @param x number for which to calculate the perfect power.
*/
public static int getPerfectPower(int x) {
int largestP = 1;
for (int b = 1; b < x; b++) {
for (int p = 1; p < x; p++) {
if (Math.pow(b,p) == x) {
largestP = p;
}
}
}
return largestP;
}
}
end code:
Perfect Power of 17 is 1
TimeExec: Get Perfect Power of 17: 0.001s
Perfect Power of 625 is 2
TimeExec: Get Perfect Power of 625: 0.026s
Perfect Power of 1024 is 2
TimeExec: Get Perfect Power of 1024: 0.052s
Perfect Power of 10000 is 2
TimeExec: Get Perfect Power of 10000: 1.9s
need this code here to print under .01s
Perfect Power of 1073741824 is X
TimeExec: Get Perfect Power of : XX.XXXs
答案1
得分: 1
首先,我们正在寻找给定参数中完全幂次数的最大*指数*。最大*指数*的最佳候选是基数为2,因此我们将循环从2开始,而不是从1开始。
其次,最小的*指数*是2(除了回退的1),因此使得*基数<sup>2</sup> = x*的最大*基数*是*maxBase = sqrt(x)*,因此我们将在那个*基数*值结束循环。
我们的目标是公式*b<sup>p</sup> = x*,我们从参数中得到`x`,从循环中得到`b`,所以我们可以使用*p = log(x) / log(b)*来计算`p`,然后检查它是否是整数。
避免舍入误差的最佳方法是四舍五入到最近的整数,然后检查*b<sup>p</sup> == x*。
用于此的代码如下:
```lang-java
public static int getPerfectPower(int x) {
double maxBase = Math.sqrt(x);
for (int b = 2; b <= maxBase; b++) {
long p = Math.round(Math.log(x) / Math.log(b));
if (Math.pow(b, p) == x)
return (int) p;
}
return 1;
}
测试
public static void main(String[] args) {
test(17);
test(625);
test(1024);
test(10000);
test(1073741824);
}
static void test(int x) {
long start = System.nanoTime();
int exponent = getPerfectPower(x);
long end = System.nanoTime();
System.out.printf("Perfect Power of %d is %d (%.9fs)%n",
x, exponent, (end - start) / 1e9);
}
输出
Perfect Power of 17 is 1 (0.000022500s)
Perfect Power of 625 is 4 (0.000003700s)
Perfect Power of 1024 is 10 (0.000003700s)
Perfect Power of 10000 is 4 (0.000003500s)
Perfect Power of 1073741824 is 30 (0.000001700s)
或者,我们可以循环指数而不是基数,将时间复杂度从_O(sqrt(x))_ 更改为 O(log(x)),这在技术上更快,但这里的值太小,以至于不会注意到任何性能差异。
没有进一步的解释,以下是代码:
public static int getPerfectPower(int x) {
// x = b ^ p <==> p = log(x) / log(b) <==> b = exp(log(x) / p)
double logX = Math.log(x);
int maxExp = (int) Math.round(logX / Math.log(2));
for (int p = maxExp; p > 1; p--) {
long b = Math.round(Math.exp(logX / p));
if (Math.pow(b, p) == x)
return p;
}
return 1;
}
英文:
First, we're looking for the maximum exponent for the perfect power number given in the parameter. The best candidate for the maximum exponent is a base of 2, so we'll start the loop at 2, not 1.
Second, the smallest exponent is 2 (other than the fallback 1), so the maximum base where base<sup>2</sup> = x, is maxBase = sqrt(x), so we'll end the loop at that base value.
We're targeting the formula b<sup>p</sup> = x, and we have x
from parameter and b
from the loop, so we can calculate p
using p = log(x) / log(b), then check if that's an integer.
Best way to do that, avoiding rounding errors, is to round to nearest integer, then checking if b<sup>p</sup> == x.
The code for that is:
public static int getPerfectPower(int x) {
double maxBase = Math.sqrt(x);
for (int b = 2; b <= maxBase; b++) {
long p = Math.round(Math.log(x) / Math.log(b));
if (Math.pow(b, p) == x)
return (int) p;
}
return 1;
}
Tests
public static void main(String[] args) {
test(17);
test(625);
test(1024);
test(10000);
test(1073741824);
}
static void test(int x) {
long start = System.nanoTime();
int exponent = getPerfectPower(x);
long end = System.nanoTime();
System.out.printf("Perfect Power of %d is %d (%.9fs)%n",
x, exponent, (end - start) / 1e9);
}
Output
Perfect Power of 17 is 1 (0.000022500s)
Perfect Power of 625 is 4 (0.000003700s)
Perfect Power of 1024 is 10 (0.000003700s)
Perfect Power of 10000 is 4 (0.000003500s)
Perfect Power of 1073741824 is 30 (0.000001700s)
Alternatively, we can loop the exponent instead of the base, changing time complexity from O(sqrt(x)) to O(log(x)), which is technically faster, but the values here are too small to notice any performance difference.
Without further explanation, here's the code:
public static int getPerfectPower(int x) {
// x = b ^ p <==> p = log(x) / log(b) <==> b = exp(log(x) / p)
double logX = Math.log(x);
int maxExp = (int) Math.round(logX / Math.log(2));
for (int p = maxExp; p > 1; p--) {
long b = Math.round(Math.exp(logX / p));
if (Math.pow(b, p) == x)
return p;
}
return 1;
}
答案2
得分: 0
你正在使用嵌套的两个循环从1循环到x来测试过多的情况。
对于指数 p
,你可以计算最可能的底数为 b0=floor(pow(x,1.0/p))
。如果你想要谨慎的话,可以测试 b=b0-1, b0, b0+1
的幂是否等于 x
,但情况 b=b0-1
永远不应该成立。
然后,当达到 b0=1
时,你可以停止增加指数。
英文:
You are testing too many cases with the nested two loops from 1 to x.
For an exponent p
you can compute the most likely base as b0=floor(pow(x,1.0/p))
. If you want to be cautious then test the powers of b=b0-1, b0, b0+1
for being equal to x
, but the case b=b0-1
should never be valid.
You can then stop increasing the exponents when b0=1
has been reached.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论