Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/89.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_Performance_Biginteger_Perfect Numbers - Fatal编程技术网

如何改进Java代码以生成所有已知的完美数?

如何改进Java代码以生成所有已知的完美数?,java,algorithm,performance,biginteger,perfect-numbers,Java,Algorithm,Performance,Biginteger,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,

我试图用欧几里德-欧拉定理生成所有已知的完美数

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

这是我的密码:

   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秒。
谢谢

我重写了公式,以适应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方法快速计算。它是最快的,因为它只使用一个位

这是完整的代码,我的机器中所有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;
   }

我重写了公式,以适应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方法快速计算。它是最快的,因为它只使用一个位

这是完整的代码,我的机器中所有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;
   }

你的输入值是多少?你应该在我们的姐妹网站上发布这个。确保包含任何人都可以复制/粘贴并运行的完整功能代码。具体来说,您需要将函数放在类中,并包含一个主函数来显示如何调用它。因为您只需要增加2个大的幂,所以应该使用BigIntegerSiftLeft而不是BigIntegerpow。在这里,它将是最合适的,获取一个0 BigInteger,然后设置获得2^n所需的位位置。@JacobG:这不会有太大区别,因为pow包含将2的幂作为特例处理的代码,并且-猜猜是什么-只是将参数向左移动。多少的输入值是多少?你应该在我们的姐妹网站上发布这个。确保包含任何人都可以复制/粘贴并运行的完整功能代码。具体来说,您需要将函数放在类中,并包含一个主函数来显示如何调用它。因为您只需要增加2个大的幂,所以应该使用BigIntegerSiftLeft而不是BigIntegerpow。在这里,它将是最合适的,获取一个0 BigInteger,然后设置获得2^n所需的位位置。@JacobG:这不会有太大区别,因为pow包含将2的幂作为特例处理的代码,并且-猜猜看-只是将参数向左移动。哇!在我的电脑里需要0.3秒。哇!在我的电脑里,需要0.3秒。