我正在研究一个因子分解问题,对于少数问题,它运作良好。我已经能够计算小数字的因子(得到Wolfram Alpha的答案),比如维基百科页面(5959)上的那些。
除了维基百科页面,我一直following this guide。再一次,由于我的数学知识非常差,我无法遵循接下来需要做的事情。
编辑:终于有效了!一旦我完全正常工作,我就会把工作代码发布到这里,这样我的困境中的其他人就可以从中学习。
答案 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()
来检查root
是n
的近似根,而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();
}
}