Wednesday, April 21, 2010

Factorising program not working. Help required.

Programmer Question

I am working on a factorisation problem using Fermat's Factorization and for small numbers it is working well. I've been able to calculate the factors (getting the answers from Wolfram Alpha) for small numbers, like the one on the Wikipedia page (5959).



Just when I thought I had the problem licked I soon realised that my program was not working when it came to larger numbers. The program follows through the examples from the Wikipedia page, printing out the values a, b, a2 and b2; the results printed for large numbers are not correct. I've followed the pseudocode provided on the Wikipedia page, but am struggling to understand where to go next.



Along with the Wikipedia page I have been following this guide. Once again, as my Math knowledge is pretty poor I cannot follow what I need to do next. The code I am using so far is as follows:



import java.math.BigInteger;

/**
*
* @author AlexT
*/
public class Fermat {

private BigInteger a, b;
private BigInteger b2;

private static final BigInteger TWO = BigInteger.valueOf(2);

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

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

public void fermat(BigInteger N) {
// a <- ceil(sqrt(N))
a = sqrt(N);
a = a.add(BigInteger.ONE);

// b2 <- a*a-N
b2 = (a.multiply(a)).subtract(N);

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


// while b2 not square root
while(!(isSqrt(b2, root))) {
// a <- a + 1
a = a.add(BigInteger.ONE);
// b2 <- (a * a) - N
b2 = (a.multiply(a)).subtract(N);
root = root.add(b2.divide(root)).divide(TWO);
}

b = sqrt(b2);

BigInteger a2 = a.pow(2);

// Wrong
BigInteger sum = (a.subtract(b)).multiply((a.add(b)));

// Factors
BigInteger fact1 = a.subtract(b);
BigInteger fact2 = a.add(b);

System.out.println("F1: " + fact1 + "\nF2: " + fact2);

//if(sum.compareTo(N) == 0) {
//System.out.println("A: " + a + "\nB: " + b);
//System.out.println("A^2: " + a2 + "\nB^2: " + b2);
//}
}

/**
* Is the number provided a perfect Square Root?
* @param n
* @param root
* @return
*/
private static boolean isSqrt(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;
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Fermat fermat = new Fermat();
//Works
//fermat.fermat(new BigInteger("5959"));

// Doesn't Work
fermat.fermat(new BigInteger("90283"));
}
}


If anyone can help me out with this problem I'll be eternally grateful.



Find the answer here

1 comment:

LinkWithin

Related Posts with Thumbnails