I am writing a program to factor stupidly large integers (5000 digits+), and performance is obviously critical. A currently TODO feature is to factor semiprimes, specifically RSA, which is why the cube root function is included. Don't tell me it's impossible. I'm trying to learn, not actually do it. Before I start on the actual factorization, I would love review on the current program. I'm not 100% on the check methods, and any help on general performance would be helpful.
package pfactor;
import java.io.File;
import java.math.BigInteger;
import java.util.Scanner;
public class Factor {
static BigInteger number;
static BigInteger sqrt;
static BigInteger cbrt;
static boolean abbrev;
static final BigInteger TWO = new BigInteger("2");
static final BigInteger THREE = new BigInteger("3");
public static void main(String[] args) throws Exception {
System.out.println("Abbreviate Numbers?");
abbrev = ask("Do you want to abbreviate numbers? ");
number = new BigInteger(getFile());
System.out.println("Factoring: \n\n" + abbreviate(number));
sqrt = sqrt(number);
System.out.println("The square root is: " + abbreviate(sqrt));
System.out.println("Difference: " + abbreviate(number.subtract((sqrt.multiply(sqrt))).abs()));
System.out.println("Check returns: " + checksqrt());
cbrt = cbrt(number);
System.out.println("The cube root is: " + abbreviate(cbrt));
System.out.println("Difference: " + abbreviate(number.subtract((cbrt.multiply(cbrt).multiply(cbrt))).abs()));
System.out.println("Check returns: " + checksqrt());
}
public static String getFile() throws Exception {
Scanner s = new Scanner(new File("Number.dat"));
String i = "";
while (s.hasNextLine()) {
i = i + s.nextLine();
}
return i;
}
public static BigInteger sqrt(BigInteger n) {
BigInteger guess = n.divide(BigInteger.valueOf((long) n.bitLength() / 2));
boolean go = true;
int c = 0;
BigInteger test = guess;
while (go) {
BigInteger numOne = guess.divide(TWO);
BigInteger numTwo = n.divide(guess.multiply(TWO));
guess = numOne.add(numTwo);
if (numOne.equals(numTwo)) {
go = false;
}
if (guess.mod(TWO).equals(BigInteger.ONE)) {
guess = guess.add(BigInteger.ONE);
}
//System.out.println(guess.toString());
c++;
c %= 5;
if (c == 4 && (test.equals(guess))) {
return guess;
}
if (c == 2) {
test = guess;
}
}
if ((guess.multiply(guess)).equals(number)) {
return guess;
}
return guess.add(BigInteger.ONE);
}
public static BigInteger cbrt(BigInteger n) {
BigInteger guess = n.divide(BigInteger.valueOf((long) n.bitLength() / 3));
boolean go = true;
int c = 0;
BigInteger test = guess;
while (go) {
BigInteger numOne = n.divide(guess.multiply(guess));
BigInteger numTwo = guess.multiply(TWO);
guess = numOne.add(numTwo).divide(THREE);
if (numOne.equals(numTwo)) {
go = false;
}
if (guess.mod(TWO).equals(BigInteger.ONE)) {
guess = guess.add(BigInteger.ONE);
}
// System.out.println(guess.toString());
c++;
c %= 5;
if (c == 4 && (test.equals(guess))) {
return guess;
}
if (c == 2) {
test = guess;
}
}
if ((guess.multiply(guess)).equals(number)) {
return guess;
}
return guess.add(BigInteger.ONE);
}
public static int[] fac() {
//Factor method TODO, does nothing, never called
return new int[5];
}
public static boolean checksqrt() {
if ((sqrt.multiply(sqrt)).equals(number)) {
return true;
}
BigInteger margin = number.subtract((sqrt.multiply(sqrt))).abs();
BigInteger maxError = (sqrt.subtract(BigInteger.ONE)).multiply(TWO);
if (margin.compareTo(maxError) == -1) {
return true;
}
return false;
}
public static boolean checkcbrt() {
if ((cbrt.multiply(cbrt).multiply(cbrt)).equals(number)) {
return true;
}
BigInteger margin = number.subtract((cbrt.multiply(cbrt).multiply(cbrt))).abs();
BigInteger c = cbrt.subtract(BigInteger.ONE);
BigInteger maxError = ((c.multiply(c)).multiply(THREE)).add(c.multiply(THREE));
if (margin.compareTo(maxError) == -1) {
return true;
}
return false;
}
public static String abbreviate(BigInteger n) {
if (abbrev)
return n.toString().substring(0, 3) + "..." + n.mod(new BigInteger("1000")) + "(" + n.toString().length() + " digits)";
return n.toString();
}
public static boolean ask(String prompt) {
Scanner s = new Scanner(System.in);
System.out.println(prompt + "(Y/N)");
char c = s.nextLine().charAt(0);
if (c == 'N' || c == 'n') {
return false;
}
if (c == 'Y' || c == 'y') {
return true;
}
return ask("");
}
}