如何在Java中有效地生成完美的数字到数字不变数?

时间:2017-11-09 16:02:39

标签: java loops math

PDDI是一个数字,这样一个数字就是所有提到的数字的总和等于数字本身。

例如,3435 =(3 ^ 3)+(4 ^ 4)+(3 ^ 3)+(5 ^ 5)

下面的代码需要很长时间来检查一个到一个巨大数字之间的PDDI。有没有办法让它更快?

    System.out.print("Enter the number");
    Scanner s = new Scanner(System.in);
    int n = s.nextInt();

    int m = 0, sum = 0, k = 0;
    // We're going to try all integers between one to n.
    for(int i = 1; i<=n; i++){
       sum = 0;
       m = i;
       while(m>0){
          k = m % 10;
          sum = sum + (int)Math.pow(k, k);
          m = m/10;
       }

       if(i == sum)
          System.out.println(i);
    }

2 个答案:

答案 0 :(得分:1)

从0到9到2的幂的数字可以预先计算并保存在一个数组中。

int powered [] = new int [10];
powered[0] = 0;
powered[1] = 1;
powered[2] = 4;
..
powered[9] = 81;

然后,对于每个数字,使用数字作为有源阵列的索引来获取有电号码。

例如234powered[2] + powered[3] + powered[4]

这将节省一些数学运算。

你也可以想到一个多线程方法,有N个线程并行执行不同数字的计算。

答案 1 :(得分:0)

使用缓存值而不是Math.pow

由于您仅使用0到9之间的电源,因此您可以将这些值缓存在int[]中,而不是每次都计算Math.pow(k, k)。它不会有那么大的改善,但是,这是一个开始。

int[] pows = new int[] {0, 1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489 };
for (int i = 0; i < 10; ++i) {
    pows[i] = (int) Math.pow(i, i);
}

System.out.print("Enter the number");
Scanner s = new Scanner(System.in);
int n = s.nextInt();

int m = 0, sum = 0, k = 0;
// We're going to try all integers between one to n.
for(int i = 1, i<=n, i++){
   sum = 0;
   m = i;
   while(m>0){
      k = m % 10;
      sum = sum + pows[k]; // use cached values here
      m = m/10;
   }

   if(i == sum)
      System.out.println(i);
}

跳过无用的值

基于逻辑,您可以跳过一些迭代。 让我们以281为例,给出4 + 16777216 + 1 = 16777251,结果大于281,所以没有变化282,283,284,... 289给出的数字等于281。 在这种情况下,您可能希望通过手动递增i来跳过这些无用的迭代。

int[] pows = new int [10];
for (int i = 0; i < 10; ++i) {
    pows[i] = (int) Math.pow(i, i);
}

System.out.print("Enter the number");
Scanner s = new Scanner(System.in);
int n = s.nextInt();

int m = 0, sum = 0, k = 0, lastNumberDigit;
// We're going to try all integers between one to n.
for(int i = 1, i<=n, i++){
   sum = 0;
   m = i;
   while(m>0){
      lastNumberDigit = m; // on the last iteration, we'll get the last digit
      k = m % 10;
      sum = sum + pows[k]; // use cached values here
      m = m/10;
   }

   if(i == sum) {
      System.out.println(i);
   } else if (sum > i) {
      i += (10 - lastNumberDigit - 1); // jump to the next decade (-1 because the for will apply i++ on it)
   }
}

我在十年中使用了这个逻辑,但你可能想将它扩展到数百甚至更多,但它会更加棘手。