【问题标题】:Fermats factorization method not functioning费马分解方法不起作用
【发布时间】:2013-02-25 17:39:33
【问题描述】:

我正在开发一个程序来比较大整数分解的不同算法。我在比较中包括的一种算法是费马分解方法。该算法似乎适用于小数字,但当我得到更大的数字时,我会得到奇怪的结果。

这是我的代码:

public void fermat(long n)
{
    ArrayList<Long> factors = new ArrayList<Long>();
    a = (long)Math.ceil(Math.sqrt(n));
    b = a*a - n;
    b_root = (long)(Math.sqrt(b)+0.5);
    while(b_root*b_root != b)
    {
        a++;
        b = a*a - n;
        b_root = (long)(Math.sqrt(b)+0.5);
    }
    factors.add(a-b_root);
    factors.add(a+b_root);
}

现在,当我尝试分解 42139523531366663 时,我得到了结果因子 61942354792984853201,这是不正确的,因为 6194235479 * 2984853201 = 18488883597240918279。我认为我得到了这个结果是因为在算法的某个地方,我到达了一个数字变得太大或类似的点,所以算法因此有点混乱。我添加了一个检查,计算两个因子的乘积并与输入值进行比较,以便在分解错误时收到警报:

long x,y;
x = factors.get(0);
y = factors.get(1);
if(x*y!=n)
    System.out.println("Faulty factorization.");

有趣的是,检查结果为真,但我没有收到警报。我尝试只打印乘法的结果,这实际上导致了输入值。所以我的问题是为什么我的程序会这样,我该怎么办?

【问题讨论】:

    标签: java factorization


    【解决方案1】:

    看起来 long 某处有溢出,因为 long 有 64 位并且

    42139523531366663 + 2^64 = 18488883597240918279
    

    对于足够大的数字,您可能需要改用BigInteger

    【讨论】:

    • 所以我得到的因子是正确的模 2^64?我懂了。不过,使用 BigInteger 可能会很困难,因为我还没有找到任何简单的方法来计算 BigInteger 的平方根。我将不得不为此寻找解决方案。谢谢!
    • 您可以使用二分法:正整数 x > 1 的平方根必须在 1 和 x 之间,因此计算中点,对其平方,然后在平方根所在的剩余一半上递归,当两个端点相等时停止。或者使用牛顿的导数方法,甚至是赫伦的方法,它可以追溯到大约三千年前的古巴比伦人;使用整数都可以很好地工作。如果您自己无法弄清楚,请提出一个单独的问题。
    【解决方案2】:

    是不是因为大数相乘也有错误?

    这可能是一个足够充分的理由。这就是让程序认为它的因式分解是正确的原因,但是当您在不使用程序的情况下实际乘以数字时,您会发现错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      • 2017-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多