简体   繁体   English

如何有效地在Java中生成Perfect数位不变数字?

[英]How do I effectively generate Perfect digit-to-digit invariant numbers in Java?

A PDDI is a number such the the sum of all the digits raised to themselves is equal to the number itself. PDDI是一个数字,因此加到自己的所有数字的总和等于该数字本身。

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

The code below takes too long to check for PDDIs between one to a huge number. 下面的代码需要很长时间才能检查一个到一个巨大的PDDI。 Is there any way to make it faster? 有什么方法可以使其更快?

    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);
    }

The number from 0 to 9 to the power of 2 can be precalculated and kept in a an array. 可以预先计算从0到9到2的幂的数字并将其保存在数组中。

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

Then for each digit fech the powered number using the digit as an index to the powered array. 然后,对于每个数字,使用数字作为幂阵列的索引来获取幂数。

For example 234 would be powered[2] + powered[3] + powered[4] 例如234将被powered[2] + powered[3] + powered[4]

This will save some math operations. 这将节省一些数学运算。

Also you could think of a multithreaded approach having N threads doing the calculations for different numbers in parallel. 您还可以想到一种多线程方法,该方法具有N个线程并行进行不同数量的计算。

Use cached values instead of Math.pow 使用缓存的值而不是Math.pow

Since you are using only power from 0 to 9, you could cache these values in a int[] instead of computing Math.pow(k, k) everytime. 由于只使用0到9的幂,因此可以将这些值缓存在int[]而不是每次都计算Math.pow(k, k) It won't improve that much but, it's a start. 不会有太大改善,但这只是一个开始。

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);
}

Skip useless values 跳过无用的值

Based on logic you may skip some iterations. 根据逻辑,您可以跳过一些迭代。 Lets take the number 281 as an example, which gives 4 + 16777216 + 1 = 16777251 , the result is above 281, so theres no changes that 282, 283, 284, ... 289 gives a number equals to 281. In such cases you may want to skip these useless iterations by manually incrementing i . 让我们以数字281为例,给出4 + 16777216 + 1 = 16777251 ,结果在281以上,因此不会发生变化, 4 + 16777216 + 1 = 16777251 ,... 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)
   }
}

I used this logic on decade, but you may want to extend it to hundreds or even more, but it will be much more tricky. 我在十年中使用了这种逻辑,但是您可能希望将其扩展到数百甚至更多,但是要棘手得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM