java - 计算 2 的极大次方

标签 java primes

我用 Java 编写了一个计算 2 的幂的程序,但它似乎效率很低。对于较小的幂(例如 2^4000),它会在不到一秒的时间内完成。但是,我正在计算 2^43112609,它比已知的最大素数大 1。超过 1200 万位数字,将需要很长时间才能运行。到目前为止,这是我的代码:

import java.io.*;

public class Power
{
 private static byte x = 2;
 private static int y = 43112609;
 private static byte[] a = {x};
 private static byte[] b = {1};
 private static byte[] product;
 private static int size = 2;
 private static int prev = 1;
 private static int count = 0;
 private static int delay = 0;
 public static void main(String[] args) throws IOException
 {
  File f = new File("number.txt");
  FileOutputStream output = new FileOutputStream(f);
  for (int z = 0; z < y; z++)
  {
   product = new byte[size];
   for (int i = 0; i < a.length; i++)
   {
    for (int j = 0; j < b.length; j++)
    {
     product[i+j] += (byte) (a[i] * b[j]);
     checkPlaceValue(i + j);
    }
   }
   b = product;
   for (int i = product.length - 1; i > product.length - 2; i--)
   {
    if (product[i] != 0)
    {
     size++;
     if (delay >= 500) 
     {
      delay = 0;
      System.out.print(".");
     }
     delay++;
    }
   }
  }
  String str = "";
  for (int i = (product[product.length-1] == 0) ? 
   product.length - 2 : product.length - 1; i >= 0; i--)
  {
   System.out.print(product[i]);
   str += product[i];
  }
  output.write(str.getBytes());
  output.flush();
  output.close();
  System.out.println();
 }

 public static void checkPlaceValue(int placeValue)
 {
  if (product[placeValue] > 9)
  {
   byte remainder = (byte) (product[placeValue] / 10);
   product[placeValue] -= 10 * remainder;
   product[placeValue + 1] += remainder;
   checkPlaceValue(placeValue + 1);
  }
 }  
}

这不是用于学校项目或其他任何东西;就是图个好玩儿。任何有关如何提高效率的帮助将不胜感激!谢谢!

凯尔

附言我没有提到输出应该是 base-10,而不是二进制。

最佳答案

这里的关键是要注意:

2^2 = 4
2^4 = (2^2)*(2^2)
2^8 = (2^4)*(2^4)
2^16 = (2^8)*(2^8)
2^32 = (2^16)*(2^16)
2^64 = (2^32)*(2^32)
2^128 = (2^64)*(2^64)
... and in total of 25 steps ...
2^33554432 = (2^16777216)*(16777216)

从那以后:

2^43112609 = (2^33554432) * (2^9558177)

您可以使用相同的方法找到剩余的(2^9558177),并且由于(2^9558177 = 2^8388608 * 2^1169569),您可以用同样的方法找到2^1169569,由于(2^1169569 = 2^1048576 * 2^120993),你可以找到2^120993 使用相同的方法,依此类推...

编辑:之前这部分有错误,现在已修复:

此外,通过注意进一步简化和优化:

2^43112609 = 2^(0b10100100011101100010100001)
2^43112609 = 
      (2^(1*33554432))
    * (2^(0*16777216))
    * (2^(1*8388608))
    * (2^(0*4194304))
    * (2^(0*2097152))
    * (2^(1*1048576))
    * (2^(0*524288))
    * (2^(0*262144))
    * (2^(0*131072))
    * (2^(1*65536))
    * (2^(1*32768))
    * (2^(1*16384))
    * (2^(0*8192))
    * (2^(1*4096))
    * (2^(1*2048))
    * (2^(0*1024))
    * (2^(0*512))
    * (2^(0*256))
    * (2^(1*128))
    * (2^(0*64))
    * (2^(1*32))
    * (2^(0*16))
    * (2^(0*8))
    * (2^(0*4))
    * (2^(0*2))
    * (2^(1*1))

另请注意,2^(0*n) = 2^0 = 1

利用这个算法,可以计算出2^12^22^42的表格^8, 2^16 ... 2^33554432 25 次乘法。然后,您可以将 43112609 转换为其二进制表示形式,并使用少于 25 次乘法轻松找到 2^43112609。总的来说,您需要使用少于 50 次乘法来找到任何 2^n,其中 n 介于 0 和 67108864 之间。

关于java - 计算 2 的极大次方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4102010/

相关文章:

java - 即使文件路径正确,FXML 文件也不会加载

java - 在一个字符串中搜索多个字符串的最快方法

c - 我的代码中的段错误

prolog - 生成素数列表

python - 可以写成两个数 x 和 y 的平方和的素数

Java正则表达式获取img src

java - 使用 BeanDefinitionRegistryPostProcessor 从 org.springframework.core.env.PropertySource 加载配置 POJO

java - 如何从返回文件名及其文件夹名称的文件夹中递归检索文件

java - 如何判断一个数是否为质数

algorithm - 如何将数字表示为 4 个素数之和?