Factorising program not working. Help required.

Posted by Ender on Stack Overflow See other posts from Stack Overflow or by Ender
Published on 2010-04-21T20:14:39Z Indexed on 2010/04/21 20:23 UTC
Read the original article Hit count: 298

Filed under:
|
|

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 void fermat(BigInteger N) {
    // floor(sqrt(N))
    BigInteger tmp = getIntSqrt(N);
    // a <- ceil(sqrt(N))
    a = tmp.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 = getIntSqrt(b2);

    BigInteger a2 = a.pow(2);

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

    //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;
}


public BigInteger getIntSqrt(BigInteger x) { // It returns s where s^2 < x < (s+1)^2
    BigInteger s; // final result
    BigInteger currentRes = BigInteger.valueOf(0); // init value is 0
    BigInteger currentSum = BigInteger.valueOf(0); // init value is 0
    BigInteger sum = BigInteger.valueOf(0);
    String xS = x.toString(); // change input x to a string xS

    int lengthOfxS = xS.length();
    int currentTwoBits;
    int i=0; // index
    if(lengthOfxS % 2 != 0) {// if odd length, add a dummy bit
        xS = "0".concat(xS); // add 0 to the front of string xS
        lengthOfxS++;
    }

    while(i < lengthOfxS){ // go through xS two by two, left to right
        currentTwoBits = Integer.valueOf(xS.substring(i,i+2));
        i += 2;

        // sum = currentSum*100 + currentTwoBits
        sum = currentSum.multiply(BigInteger.valueOf(100));
        sum = sum.add(BigInteger.valueOf(currentTwoBits));
        // subtraction loop
        do {
            currentSum = sum; // remember the value before subtract
            // in next 3 lines, we work out
            // currentRes = sum - 2*currentRes - 1
            sum = sum.subtract(currentRes);
            // currentRes++
            currentRes = currentRes.add(BigInteger.valueOf(1));
            sum = sum.subtract(currentRes);

        } while(sum.compareTo(BigInteger.valueOf(0)) >= 0);
        // the loop stops when sum < 0

     // go one step back
        currentRes = currentRes.subtract(BigInteger.valueOf(1));
        currentRes = currentRes.multiply(BigInteger.valueOf(10));
    }
    s = currentRes.divide(BigInteger.valueOf(10)); // go one step back
    return s;
}

/**
 * @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.

© Stack Overflow or respective owner

Related posts about java

Related posts about factorisation