How to resolve the algorithm Fermat numbers step by step in the Java programming language
How to resolve the algorithm Fermat numbers step by step in the Java programming language
Table of Contents
Problem Statement
In mathematics, a Fermat number, named after Pierre de Fermat who first studied them, is a positive integer of the form Fn = 22n + 1 where n is a non-negative integer. Despite the simplicity of generating Fermat numbers, they have some powerful mathematical properties and are extensively used in cryptography & pseudo-random number generation, and are often linked to other number theoric fields. As of this writing, (mid 2019), there are only five known prime Fermat numbers, the first five (F0 through F4). Only the first twelve Fermat numbers have been completely factored, though many have been partially factored.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Fermat numbers step by step in the Java programming language
The provided Java code focuses on exploring Fermat numbers and their prime factorization.
Fermat numbers are defined as F[n] = 2^(2^n) + 1
. The code calculates the first 10 Fermat numbers and then factorizes the first 12 of them.
-
Calculating Fermat Numbers:
- The
fermat
method computes the Fermat number for a given indexn
by raising 2 to the power of2 ^ n
and adding 1.
- The
-
Factorizing Fermat Numbers:
- The
getFactors
method finds the prime factors of a given Fermat numbern
. It uses a combination of trial division and Pollard's rho algorithm. - Trial division checks if
n
is prime (probable prime with 100 iterations) or if it starts with a known composite pattern (stored in theCOMPOSITE
map). If not, it applies Pollard's rho algorithm to find a factorfactor
. factor
is added to the list of factors, andn
is divided byfactor
to continue the factorization process untiln
becomes prime.
- The
-
Pollard's Rho Algorithm:
- The
pollardRhoFast
method implements a variant of Pollard's rho algorithm, an integer factorization method. It iteratively calculatesx
andy
values based on the numbern
. - By comparing the difference between
x
andy
, it attempts to find a non-trivial factor ofn
. - The algorithm is optimized using a speed-up technique that involves 100 iterations and one GCD calculation, reducing the factorization time.
- The
-
Printing the Results:
- The program displays the first 10 Fermat numbers and the factorization of the first 12 Fermat numbers using the
getString
method, which converts the list of factors into a string representation.
- The program displays the first 10 Fermat numbers and the factorization of the first 12 Fermat numbers using the
The code provides a detailed demonstration of Fermat numbers, their factorization, and the use of Pollard's rho algorithm for integer factorization.
Source code in the java programming language
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class FermatNumbers {
public static void main(String[] args) {
System.out.println("First 10 Fermat numbers:");
for ( int i = 0 ; i < 10 ; i++ ) {
System.out.printf("F[%d] = %s\n", i, fermat(i));
}
System.out.printf("%nFirst 12 Fermat numbers factored:%n");
for ( int i = 0 ; i < 13 ; i++ ) {
System.out.printf("F[%d] = %s\n", i, getString(getFactors(i, fermat(i))));
}
}
private static String getString(List<BigInteger> factors) {
if ( factors.size() == 1 ) {
return factors.get(0) + " (PRIME)";
}
return factors.stream().map(v -> v.toString()).map(v -> v.startsWith("-") ? "(C" + v.replace("-", "") + ")" : v).collect(Collectors.joining(" * "));
}
private static Map<Integer, String> COMPOSITE = new HashMap<>();
static {
COMPOSITE.put(9, "5529");
COMPOSITE.put(10, "6078");
COMPOSITE.put(11, "1037");
COMPOSITE.put(12, "5488");
COMPOSITE.put(13, "2884");
}
private static List<BigInteger> getFactors(int fermatIndex, BigInteger n) {
List<BigInteger> factors = new ArrayList<>();
BigInteger factor = BigInteger.ONE;
while ( true ) {
if ( n.isProbablePrime(100) ) {
factors.add(n);
break;
}
else {
if ( COMPOSITE.containsKey(fermatIndex) ) {
String stop = COMPOSITE.get(fermatIndex);
if ( n.toString().startsWith(stop) ) {
factors.add(new BigInteger("-" + n.toString().length()));
break;
}
}
factor = pollardRhoFast(n);
if ( factor.compareTo(BigInteger.ZERO) == 0 ) {
factors.add(n);
break;
}
else {
factors.add(factor);
n = n.divide(factor);
}
}
}
return factors;
}
private static final BigInteger TWO = BigInteger.valueOf(2);
private static BigInteger fermat(int n) {
return TWO.pow((int)Math.pow(2, n)).add(BigInteger.ONE);
}
// See: https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
@SuppressWarnings("unused")
private static BigInteger pollardRho(BigInteger n) {
BigInteger x = BigInteger.valueOf(2);
BigInteger y = BigInteger.valueOf(2);
BigInteger d = BigInteger.ONE;
while ( d.compareTo(BigInteger.ONE) == 0 ) {
x = pollardRhoG(x, n);
y = pollardRhoG(pollardRhoG(y, n), n);
d = x.subtract(y).abs().gcd(n);
}
if ( d.compareTo(n) == 0 ) {
return BigInteger.ZERO;
}
return d;
}
// Includes Speed Up of 100 multiples and 1 GCD, instead of 100 multiples and 100 GCDs.
// See Variants section of Wikipedia article.
// Testing F[8] = 1238926361552897 * Prime
// This variant = 32 sec.
// Standard algorithm = 107 sec.
private static BigInteger pollardRhoFast(BigInteger n) {
long start = System.currentTimeMillis();
BigInteger x = BigInteger.valueOf(2);
BigInteger y = BigInteger.valueOf(2);
BigInteger d = BigInteger.ONE;
int count = 0;
BigInteger z = BigInteger.ONE;
while ( true ) {
x = pollardRhoG(x, n);
y = pollardRhoG(pollardRhoG(y, n), n);
d = x.subtract(y).abs();
z = z.multiply(d).mod(n);
count++;
if ( count == 100 ) {
d = z.gcd(n);
if ( d.compareTo(BigInteger.ONE) != 0 ) {
break;
}
z = BigInteger.ONE;
count = 0;
}
}
long end = System.currentTimeMillis();
System.out.printf(" Pollard rho try factor %s elapsed time = %d ms (factor = %s).%n", n, (end-start), d);
if ( d.compareTo(n) == 0 ) {
return BigInteger.ZERO;
}
return d;
}
private static BigInteger pollardRhoG(BigInteger x, BigInteger n) {
return x.multiply(x).add(BigInteger.ONE).mod(n);
}
}
You may also check:How to resolve the algorithm Stirling numbers of the second kind step by step in the Perl programming language
You may also check:How to resolve the algorithm Eban numbers step by step in the Perl programming language
You may also check:How to resolve the algorithm Literals/String step by step in the Nim programming language
You may also check:How to resolve the algorithm Function prototype step by step in the Quackery programming language
You may also check:How to resolve the algorithm Variables step by step in the F# programming language