【问题标题】:Faster prime factorization for huge BigIntegers in JavaJava中巨大BigIntegers的更快素数分解
【发布时间】:2013-05-28 22:02:50
【问题描述】:

所以我现在正在编写一个 java 代码。我已经让它工作得很好,但是任务的重点是让它分解大数字(超过 30 位)。它会这样做,但是它可能需要超过 15 分钟才能完成,这是不好的。我的教授向我保证,我使用的算法适用于高达 2^70 的数字,并且应该在大约五分钟内完成。我一直在尝试想出一种方法来做到这一点(增加 2 而不是 1 等),但我似乎无法弄清楚如何在不跳过某些因素的情况下让它更快地移动。有任何想法吗?我还认为椭圆曲线方法会更好,但他告诉我现在不要处理这个问题。

这是我的代码(ps,sqrt 是我自己的函数,但我确信它可以工作):

public String factorizer(BigInteger monster){
    System.out.println("monster =" + monster); 
    String factors = "";  
    BigInteger top = maths.monsterSqrt(monster);   
    if(monster.mod(two).equals(0));
        BigInteger jump = two;
    for(BigInteger bi = two; bi.compareTo(top) <= 0; bi = bi.add(jump)){
        while(monster.mod(bi).equals(zero)){
            factors +=  "+" + bi + ""; 
            monster = monster.divide(bi); 
            jump = one; 
        }
    }
    if(monster.compareTo(BigInteger.ONE) == 1){
        factors  += "+" + monster; 
    } 
    return factors; 
} 

【问题讨论】:

  • 这个 if 没用 ` if(monster.mod(two).equals(0));` -> 去掉分号 * 如果你检查除以 2 的可分性(?),你应该测试3,5... then * for/while 嵌套循环有点难以理解,您应该以递归方式重写您的函数。 *我会将结果累积在例如一个 ArrayList,但这是风格问题 :-)
  • 您可以使用Stringbuilder 代替字符串来表示因子。 Class StringBuilder
  • @Gyro 这比没用还糟糕,它使整个算法无效。
  • @Smit 确实如此,但这将是整体性能中的一个非常小的因素(双关语),因为#factors 永远不会超过 70
  • @Arend:对不起,我的评论还没说完(大拇指综合症)

标签: java cryptography rsa factorization


【解决方案1】:

这是我的试除法整数分解:

public static LinkedList tdFactors(BigInteger n)
{
    BigInteger two = BigInteger.valueOf(2);
    LinkedList fs = new LinkedList();

    if (n.compareTo(two) < 0)
    {
        throw new IllegalArgumentException("must be greater than one");
    }

    while (n.mod(two).equals(BigInteger.ZERO))
    {
        fs.add(two);
        n = n.divide(two);
    }

    if (n.compareTo(BigInteger.ONE) > 0)
    {
        BigInteger f = BigInteger.valueOf(3);
        while (f.multiply(f).compareTo(n) <= 0)
        {
            if (n.mod(f).equals(BigInteger.ZERO))
            {
                fs.add(f);
                n = n.divide(f);
            }
            else
            {
                f = f.add(two);
            }
        }
        fs.add(n);
    }

    return fs;
}

这段代码在我博客上的essay中有解释,里面也有对Pollard的rho算法的解释,可能更适合分解大整数。

顺便说一句,如今 30 位数并不是一个特别大的因式分解问题。任何超过几秒钟的时间都太长了。

【讨论】:

  • 非常快!真的很喜欢!
  • 我知道这是最后一次,但我一定遗漏了一些东西......我使用最近的高端笔记本电脑在 71994651332404115788173195239 上测试了你的代码,它需要很长时间。
  • 正如我上周通过私人电子邮件告诉您的,您的号码因子为 134567897654321 * 535006138814359。是的,这需要一段时间。您将需要使用椭圆曲线或二次筛来分解该数字。
【解决方案2】:

当您将monster 除以一个素数时,您还应该相应地调整top。实际上,外部循环将始终运行到原始数字的平方根,增量为 1 或 2,对于 30 位数字,它需要 10 ^ 15 步的顺序......这很奇怪只需 15 分钟即可完成!

如果你的怪物数有非常大的质因数(比如它本身就是质数),那么无论如何你都可以忘记良好的性能。

请注意,您的示例代码中的增量是错误的:如果原始数字不是偶数,那么jump 将始终保持为two,这意味着您只研究偶数因子,因此不会找到任何因子。

【讨论】:

    【解决方案3】:

    不知道你为什么要返回一个字符串!

    这对我有用。请注意,它每次都会将in / in = n / i 进行比较:

    // Memoization of factors.
    static Map<BigInteger, List<BigInteger>> factors = new HashMap<>();
    private static final BigInteger TWO = BigInteger.ONE.add(BigInteger.ONE);
    
    public static List<BigInteger> factors(BigInteger n, boolean duplicates) {
      // Have we done this one before?
      List<BigInteger> f = factors.get(n);
      if (f == null) {
        // Start empty.
        f = new ArrayList<>();
        // Check for duplicates.
        BigInteger last = BigInteger.ZERO;
        // Limit the range as far as possible.
        for (BigInteger i = TWO; i.compareTo(n.divide(i)) <= 0; i = i.add(BigInteger.ONE)) {
          // Can have multiple copies of the same factor.
          while (n.mod(i).equals(BigInteger.ZERO)) {
            if (duplicates || !i.equals(last)) {
              f.add(i);
              last = i;
            }
            // Remove that factor.
            n = n.divide(i);
          }
        }
        if (n.compareTo(BigInteger.ONE) > 0) {
          // Could be a residue.
          if (duplicates || n != last) {
            f.add(n);
          }
        }
        // Memoize.
        factors.put(n, f);
      }
      return f;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-06
      • 1970-01-01
      • 2012-05-20
      相关资源
      最近更新 更多