【问题标题】:How can I improve my Java code to generate all known Perfect numbers?如何改进我的 Java 代码以生成所有已知的完美数字?
【发布时间】:2020-02-12 18:19:52
【问题描述】:

我正在尝试使用Euclid–Euler theorem 生成所有已知的perfect numbers

我想知道是否可以修改/重写我的代码以快速获得结果

这是我的代码:

   public static BigInteger[] genAllPerfect(int howMany)
   {
      int[] expn = { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689,
            9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269,
            2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657, 37156667, 42643801,
            43112609, 57885161, 74207281, 77232917, 82589933 };

      BigInteger[] perfectNums = new BigInteger[51];
      BigInteger One = BigInteger.ONE;
      BigInteger Two = One.add(One);

      for (int i = 0; i < howMany; i++)
      {
         BigInteger firstPart = Two.pow(expn[i] - 1); // 2^(p-1)

         BigInteger secondPart = Two.pow(expn[i]); // 2^p

         secondPart = secondPart.subtract(One); // (2^p - 1)

         perfectNums[i] = firstPart.multiply(secondPart);
      }

      return perfectNums;
   }

此代码平均需要 30 秒。 谢谢。

【问题讨论】:

  • howMany 的输入值是多少?
  • 你应该在我们的姊妹网站Code Review上发布这个。确保包含任何人都可以复制/粘贴和运行的功能齐全的代码。具体来说,您需要将您的函数放在一个类中,并包含一个 main() 函数以显示它是如何被调用的。
  • 因为你只是提高2的一个大幂,你应该使用BigInteger#shiftLeft而不是BigInteger#pow
  • setBit() 在这里最合适,获取一个零 BigInteger,然后设置您需要获取 2^n 的位位置。
  • @JacobG.:这不会有太大区别,因为pow() 包含将 2 的幂视为特殊情况的代码,并且——猜猜看——只是将参数向左移动。

标签: java algorithm performance biginteger perfect-numbers


【解决方案1】:

我重写了公式以适应 Java BigInteger 类的 setBit() 方法以减少时间。

2^(p-1) * (2^p -1)

= (2^p)/2 * (2^p -1)

= ((2^p) * (2^p -1))/2

= (2^2p - 2^p)/2

= (2^(2p-1) - 2^(p-1))

由于2^n 可以使用BigInteger setBit() 方法快速计算。 setBit 是最快的,因为它只适用于单个位。

这是完整的代码,在我的机器中,所有 51 个完美数字大约需要 0.35 秒

public class PerfectNumbers
{
   static BigInteger[] genAllPerfect(int howMany)
   {
      if (howMany > 51)
         howMany = 51;

      int[] expn = { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689,
            9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269,
            2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657, 37156667, 42643801,
            43112609, 57885161, 74207281, 77232917, 82589933 };

      BigInteger Zero = BigInteger.ZERO;
      BigInteger[] perfectNums = new BigInteger[howMany];

      for (int i = 0; i < howMany; i++)
      {
         BigInteger perfect1 = Zero.setBit(expn[i] - 1); // 2^(p-1)

         perfectNums[i] = Zero.setBit(2 * expn[i] - 1); // 2^(2*p-1)

         perfectNums[i] = perfectNums[i].subtract(perfect1); // 2^(2*p-1) - 2^(p-1)
      }
      return perfectNums;
   }

【讨论】:

  • 哇!在我的电脑中需要 0.3 秒。
猜你喜欢
  • 2010-09-19
  • 2011-04-08
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 2015-09-16
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多