需要帮助程序的寓教于乐游戏

时间:2010-04-21 20:14:39

标签: java math

我正在研究一个因子分解问题,对于少数问题,它运作良好。我已经能够计算小数字的因子(得到Wolfram Alpha的答案),比如维基百科页面(5959)上的那些。

除了维基百科页面,我一直following this guide。再一次,由于我的数学知识非常差,我无法遵循接下来需要做的事情。

编辑:终于有效了!一旦我完全正常工作,我就会把工作代码发布到这里,这样我的困境中的其他人就可以从中学习。

3 个答案:

答案 0 :(得分:2)

那个getIntSqrt()方法......我不知道它是否正常,但它看起来很糟糕(将BigInteger转换为String?)你检查了吗?

Here是一种(显然)更好的方法。

答案 1 :(得分:1)

您的isSqrt()功能对于您尝试执行的操作不正确。你想要 知道n = root^2是否完全正确,但是如果你的IsSqrt()函数被写为返回“true” n仅位于(root^2, (root+1)^2)区间。

我认为您需要做的就是检查n是否等于root.pow(2)

答案 2 :(得分:1)

在你的循环中:

// while b2 not square
while(!(isSqrt(b2, root))) {

以下指示的目的是什么?

    root = root.add(b2.divide(root)).divide(TWO);

我认为为了检查b2是一个正方形,你应该尝试计算平方根(上面的指令只是计算平方根的规范算法的一步),方法你已经拥有:

    root = getIntSqrt(b2);

同样的观察结果适用于此代码:

// ??
final int bitLength = N.bitLength();
BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);
root = root.add(b2.divide(root)).divide(TWO);

修改的。问题是,您的sqrt()方法需要isSqrt()来检查rootn的近似根,而fermat()中的循环需要精确检查。 我附加了一些似乎通过了你最后一次测试的代码:

import java.math.BigInteger;

public class Fermat {

private BigInteger a, b, N;
private static final BigInteger TWO = BigInteger.valueOf(2);

private static boolean isApproximateSqrt(BigInteger n, BigInteger root) {
    final BigInteger lowerBound = root.pow(2);
    final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
    return lowerBound.compareTo(n) <= 0
        && n.compareTo(upperBound) < 0;
}

private static BigInteger intSqrt(BigInteger n) {
    if (n.signum() >= 0) {
        final int bitLength = n.bitLength();
        BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);

        while ( ! isApproximateSqrt(n, root) ) {
            root = root.add(n.divide(root)).divide(TWO);
        }
        return root;
    } else {
        throw new ArithmeticException("square root of negative number");
    }
}

private void init() {
    a = intSqrt(N);                             // a <- ceil(sqrt(N))
    BigInteger b2, root;
    do {
        a = a.add(BigInteger.ONE);              // a <- a + 1
        b2 = (a.multiply(a)).subtract(N);       // b2 <- (a * a) - N
        root = intSqrt(b2);
    } while( root.pow(2).compareTo(b2) != 0 );  // while b2 not exact sqrt
    b = root;
}

public void print() {
    BigInteger a2 = a.pow(2);
    BigInteger b2 = b.pow(2);
    BigInteger squareDifference = a2.subtract(b2);
    System.out.println("A: " + a + "\nB: " + b);
    System.out.println("A^2: " + a2 + "\nB^2: " + b2);
    System.out.println("N: " + N);
    if(squareDifference.compareTo(N) != 0) {
        System.out.println("Something is wrong....");
    }
}

public Fermat(BigInteger aNumber) {
    N = aNumber;
    init();
}

public static void main(String[] args) {
    Fermat f = new Fermat(new BigInteger("90283"));
    f.print();
}
}