Who wants to help me with my homework?
I'm try to implement Fermat's primality test in Java using BigIntegers. My implementation is as follows, but unfortunately it doesn't work. Any ideas?
public static boolean checkPrime(BigInteger n, int maxIterations)
{
if (n.equals(BigInteger.ONE))
return false;
BigInteger a;
Random rand = new Random();
for (int i = 0; i < maxIterations; i++)
{
a = new BigInteger(n.bitLength() - 1, rand);
a = a.modPow(n.subtract(BigInteger.ONE), n);
if (!a.equals(BigInteger.ONE))
return false;
}
return true;
}
I'm new to BigIntegers.
Thanks!
Your use of the particular BigInteger constructor is reasonable, but you should use a rejection method to select a fermat base a. Here is a slight modification of your method in a class which also uses exactly one Random object:
import java.math.BigInteger;
import java.util.Random;
public class FermatTestExample
{
private final static Random rand = new Random();
private static BigInteger getRandomFermatBase(BigInteger n)
{
// Rejection method: ask for a random integer but reject it if it isn't
// in the acceptable set.
while (true)
{
final BigInteger a = new BigInteger (n.bitLength(), rand);
// must have 1 <= a < n
if (BigInteger.ONE.compareTo(a) <= 0 && a.compareTo(n) < 0)
{
return a;
}
}
}
public static boolean checkPrime(BigInteger n, int maxIterations)
{
if (n.equals(BigInteger.ONE))
return false;
for (int i = 0; i < maxIterations; i++)
{
BigInteger a = getRandomFermatBase(n);
a = a.modPow(n.subtract(BigInteger.ONE), n);
if (!a.equals(BigInteger.ONE))
return false;
}
return true;
}
public static void main(String[] args)
{
System.out.printf("checkprime(2) is %b%n", checkPrime(BigInteger.valueOf(2L), 20));
System.out.printf("checkprime(5) is %b%n", checkPrime(BigInteger.valueOf(5L), 20));
System.out.printf("checkprime(7) is %b%n", checkPrime(BigInteger.valueOf(7L), 20));
System.out.printf("checkprime(9) is %b%n", checkPrime(BigInteger.valueOf(9L), 20));
}
}
a should be "pick a randomly in the range (1, n − 1]" and I don't really see that happening. You could print a to check that.
As for how to do that:
BigInteger a = BigInteger.valueOf(random.nextInt(n-2)+2);
e.g. You shouldn't use the BigInteger constructor with a Random argument; that's just a source of randomness, but a should be a random value.
The 'random.nextInt(n-1)+1' comes from the definition of nextInt which, given argument k, returns a random value 0 up to and including k-1. And you want a to be larger than 1 and smaller than n.
Related
It is a code that gets prime numbers, I have made it as efficient as I could, but the problem is that I can't transform it to BigInteger, as long can't hold that much information; here the code:
public class p3{
static long perfectNumber;
static long mersenne;
public static void main(String[] args) {
long p = 2;
while (true) {
if( p % 2 == 0&&p!=2){
p++;
}
else{
if (isPrime(p) == true) {
mersenne = (long) (Math.pow(2, p) - 1);
if (isPrime(mersenne) == true) {
perfectNumber = (long) Math.pow(2, (p - 1)) * mersenne;
System.out.println(perfectNumber);
}
}
p+=1;
}
}
}
private static boolean isPrime(long testPrime) {
for (long i = 3; i < Math.sqrt(testPrime); i += 2) {
if (testPrime % i == 0) {
return false;
}
}
return true;
}
}
I've tried to use BigInteger but code is not working, as I can't use
BigInteger exponents with pow
You don't need to. The exponents don't need to be nearly as large as the mersenne primes and perfect numbers. They can have their own independent isPrime() test. In fact, they need to be int, instead of long, to satisfy BigInteger.pow().
Below is what you asked for, but may not be what you want. I doubt you'll get more then one additional perfect number beyond your original code due to time constraints which is why #WJS is pushing you in a different direction.
import java.math.BigInteger;
public class p3 {
static BigInteger TWO = new BigInteger("2");
static BigInteger THREE = new BigInteger("3");
public static void main(String[] args) {
int p = 2;
while (true) {
if (isPrime(p)) {
BigInteger mersenne = TWO.pow(p).subtract(BigInteger.ONE);
if (isPrime(mersenne)) {
System.out.println(TWO.pow(p - 1).multiply(mersenne));
}
}
p += (p == 2) ? 1 : 2;
}
}
private static boolean isPrime(BigInteger number) {
if (number.mod(TWO).equals(BigInteger.ZERO)) {
return number.equals(TWO);
}
for (BigInteger i = THREE; number.compareTo(i.multiply(i)) >= 0; i = i.add(TWO)) {
if (number.mod(i).equals(BigInteger.ZERO)) {
return false;
}
}
return true;
}
private static boolean isPrime(int number) {
if (number % 2 == 0) {
return number == 2;
}
for (int i = 3; number >= i * i; i += 2) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
OUTPUT
> java p3
6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
2658455991569831744654692615953842176
Your original code outputs 0 in place of the final (37 digit) number above. So the immediate issue really is that long can't hold enough information. But beyond this point, you simply can't calculate fast enough with the above algorithm.
If we do something simple-minded to my above code, like replace this line:
if (isPrime(mersenne)) {
with:
if (mersenne.isProbablePrime(10)) {
The code will spit out the first 20 perfect numbers before slowing to a crawl. Tune the certainty argument of isProbablePrime() as you see fit.
I was learning dynamic programming's application to the Fibonacci Sequence and had a question. Here is the code for reference:
import java.math.BigInteger;
import java.util.Arrays;
public class FibonacciNumbersB {
static BigInteger[] dp = new BigInteger[10000];
public static void main(String[] args) {
Arrays.fill(dp, BigInteger.ZERO);
dp[0] = BigInteger.ONE;
dp[1] = BigInteger.ONE;
for(int i = 4; i < 9999; i++)
System.out.println(fibRecurse(i).toString());
}
public static BigInteger fibRecurse(int N) {
for(int i = 2; i < N; i++) {
// For numerous calls to this function, this will save as it goes
if(dp[i].equals(BigInteger.ZERO))
dp[i] = dp[i - 1].add(dp[i - 2]);
}
return dp[N - 1];
}
}
I have a statement check if dp[i] equals 0 in the fibRecurse method (although fibRecurse isn't recursive).
Is it more efficient to check if dp[i] has been calculated already or to just let dp[i] equal to the sum of the previous two elements?
I would prefer a Map<Integer, BigInteger> over using a fixed BigInteger[] when performing this memoization. Note that your current approach is not recursive. The Map might be declared and initialized like
static Map<Integer, BigInteger> memo = new HashMap<>();
static {
memo.put(0, BigInteger.ONE);
memo.put(1, BigInteger.ONE);
}
Then check if the current n is present in the memo (if it is, return it) - otherwise, computer and store it. Like,
public static BigInteger fibRecurse(int n) {
if (memo.containsKey(n)) {
return memo.get(n);
}
BigInteger v = fibRecurse(n - 1).add(fibRecurse(n - 2));
memo.put(n, v);
return v;
}
A version without memoization would simply omit memo like
public static BigInteger fibRecurseSlow(int n) {
if (n == 0 || n == 1) return BigInteger.ONE;
BigInteger v = fibRecurse(n - 1).add(fibRecurse(n - 2));
return v;
}
I think you can infer from the method names I've chosen which is slower.
import java.math.BigInteger;
import java.util.Arrays;
public class FibonacciNumbersB {
static BigInteger[] dp = new BigInteger[10000];
public static void main(String[] args) {
dp[0] = BigInteger.ONE;
dp[1] = BigInteger.ONE;
int N = 9999;
fibRecurse(N);
for(int i = 0; i < N; i++)
System.out.println(dp[i].toString()) ;
}
public static void fibRecurse(int N) {
for(int i = 2; i < N; i++) {
dp[i] = dp[i - 1].add(dp[i - 2]);
}
}
}
The code that is for finding fibonacci sequence can be write easily.Let's consider recursive code for finding fibonacci number set.
import java.util.Scanner;
class fac{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.print("Enter Your number :");
int n=sc.nextInt();
System.out.print(fibonacci(n));
}
public static int fibonacci(int x){
if(x<2){
return 1;
}
else{
return (fibonacci(x-1)+fibonacci(x-2));
}
}
}
In this stage, there are many same subproblems are calculating again and again.So in this case, time complexity goes to height for large input. Because of that reason , dynamic programming technique was came ...In dynamic programming ,an extra table('lookUp' table) is maintained for storing previous calculated subproblems' values. before calculating next subproblems' value, check whether availability of the answer for the particular subproblem in created table('lookUp' table).If it is in the 'lookUp table', get the answer for particular subproblem. If it is not in the 'lookUp ' table, calculate value of the particular problem and store the 'lookUp ' table. That is the meaning of the dynamic programming technique.There are two ways for performing this technique.
1.Memoization -
memoization is the technique that calculating values of subproblems Top- Down manner.Let's consider the code of fibonacci sequence.
import java.util.Scanner;
class fab{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.print("Enter Your number :");
int n=sc.nextInt();
int[] lookUp=new int[n];
int i;
for(i=0;i<n;i++){
lookUp[i]=-1;
}
fibonachi(n);
}
public static void fibonachi(int x){
if(lookUp[x]==-1){
if(x<=1){
lookUp[x]=x;
}
else{
lookUp[x]=fibonachi(x-1)+fibonachi(x-2);
}
}
System.out.print(lookUp[x]);
}
}
2.Tabulation - This calculation goes to Bottom to Top manner.At first consider the base case and perform . Then perform the next steps using previous cases.Les's consider fibonacci sequence code with tabulation technique.
import java.util.Scanner;
class fac{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.print("Enter Your number :");
int n=sc.nextInt();
int[] lookUp=new int[n];
int i;
lookUp[0]=1; // store base case values in the 'lookUp' table
lookUp[1]=1;
for(i=2;i<n;i++){
lookUp[i]=lookUp[i-1]+lookUp[i-2];
}
System.out.print(lookUp[n-1]);
}
}
In this case , base case values are stored at first.then calculates next values using previous ones..In tabulation all the values must be calculated because new value calculated using previous vlues..so memoization is better than tabulation.That's all. I hope, you could get idea.Thank you!
Context: I'm trying to calculate factorials for very large n using the BigInteger class in Java (for n>100,000) and so far this what I'm doing:
Produce all primes less than or equal to n using Sieve of Erasthones
Find to which powers they will be raised.
Raise all the numbers to the respective powers.
Use a divide and conquer recursive method to multiply them all.
From the research I've done on the internet, this is asymptotically faster than simply multiplying all k up to n. However I've noticed that the slowest part of my implementation is the part where I multiply all the prime powers. My questions are:
Is there a faster way to calculate the product of lots of numbers?
Can my implementation be improved ?
Code:
public static BigInteger product(BigInteger[] numbers) {
if (numbers.length == 0)
throw new ArithmeticException("There is nothing to multiply!");
if (numbers.length == 1)
return numbers[0];
if (numbers.length == 2)
return numbers[0].multiply(numbers[1]);
BigInteger[] part1 = new BigInteger[numbers.length / 2];
BigInteger[] part2 = new BigInteger[numbers.length - numbers.length / 2];
System.arraycopy(numbers, 0, part1, 0, numbers.length / 2);
System.arraycopy(numbers, numbers.length / 2, part2, 0, numbers.length - numbers.length / 2);
return product(part1).multiply(product(part2));
}
Note that BigInteger uses the karatsuba algorithm for multiplication.
I know that there are lots of questions about calculating factorials. But mine is about calculating the product of BigIntegers for which there is not much resource. (I've seen someone say "Use Divide and Conquer method", but I don't remember where, and I haven't seen any implementation around.
One way to improve the performance is to do the following:
Sort your array of numbers you need to multiply together
Create two new lists: a and b.
For each number in the input list that you need to multiply, it is likely to appear more than once. Let's say number v_i appears n_i times. Then add v_i to the a n_i / 2 times (rounded down). If n_i is odd, add v_i once to b as well.
To compute the result, do:
BigInteger A = product(a);
BigInteger B = prudoct(b);
return a.multiply(a).multiply(b);
To see how it works, consider your input array is [2, 2, 2, 2, 3, 3, 3]. So, there are four 2s and three 3s. Arrays a and b will correspondingly be
a = [2, 2, 3]
b = [3]
Then you will recursively call to compute the product of these. Note that we reduced the number of numbers that we want to multiply from 7 to 4, almost by a factor of two. The trick here is that for numbers that occur many times, we can compute the product of only half of them, and then raise it to the power of two. Very similar to how the power of a number can be computed in O(log n) time.
I propose another idea, the pow algorithm is very fast, you can compute the all primes with the exponent, like this:
11! -> {2^10, 3^5, 5^2, 7^1, 11^1}
You can compute all primes power , and then use divide and conquer to multiply all of them.
The implementation:
private static BigInteger divideAndConquer(List<BigInteger> primesExp, int min, int max){
BigInteger result = BigInteger.ONE;
if (max - min == 1){
result = primesExp.get(min);
} else if (min < max){
int middle = (max + min)/2;
result = divideAndConquer(primesExp, min, middle).multiply(divideAndConquer(primesExp, middle, max));
}
return result;
}
public static BigInteger factorial(int n) {
// compute pairs: prime, exp
List<Integer> primes = new ArrayList<>();
Map<Integer, Integer> primeTimes = new LinkedHashMap<>();
for (int i = 2; i <= n; i++) {
int sqrt = Math.round((float) Math.sqrt(i));
int value = i;
Iterator<Integer> it = primes.iterator();
int prime = 0;
while (it.hasNext() && prime <= sqrt && value != 0) {
prime = it.next();
int times = 0;
while (value % prime == 0) {
value /= prime;
times++;
}
if (times > 0) {
primeTimes.put(prime, times + primeTimes.get(prime));
}
}
if (value > 1) {
Integer times = primeTimes.get(value);
if (times == null) {
times = 0;
primes.add(value);
}
primeTimes.put(value, times + 1);
}
}
// compute primes power:
List<BigInteger> primePows = new ArrayList<>(primes.size());
for (Entry<Integer,Integer> e: primeTimes.entrySet()) {
primePows.add(new BigInteger(String.valueOf(e.getKey())).pow(e.getValue()));
}
// it multiply all of them:
return divideAndConquer(primePows, 0, primePows.size());
}
Probably the fastest approach :
Sequence.java
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class Sequence {
private final List<BigInteger> elements;
private Sequence(List<BigInteger> elements) {
this.elements = elements;
}
public List<BigInteger> getElements() {
return elements;
}
public int size() {
return elements.size();
}
public Sequence subSequence(int startInclusive, int endExclusive) {
return subSequence(startInclusive, endExclusive, false);
}
public Sequence subSequence(int startInclusive, int endExclusive, boolean sync) {
return Sequence.of(elements.subList(startInclusive, endExclusive), sync);
}
public void addLast(BigInteger element) {
elements.add(element);
}
public BigInteger removeLast() {
return elements.remove(size() - 1);
}
public BigInteger sum() {
return sum(false);
}
public BigInteger sum(boolean parallel) {
return parallel
? elements.parallelStream().reduce(BigInteger.ZERO, BigInteger::add)
: elements.stream().reduce(BigInteger.ZERO, BigInteger::add);
}
public BigInteger product() {
return product(false);
}
public BigInteger product(boolean parallel) {
return parallel
? elements.parallelStream().reduce(BigInteger.ONE, BigInteger::multiply)
: elements.stream().reduce(BigInteger.ONE, BigInteger::multiply);
}
public static Sequence range(int startInclusive, int endExclusive) {
return range(startInclusive, endExclusive, false);
}
public static Sequence range(int startInclusive, int endExclusive, boolean sync) {
if (startInclusive > endExclusive) {
throw new IllegalArgumentException();
}
final List<BigInteger> elements = sync ? Collections.synchronizedList(new ArrayList<>()) : new ArrayList<>();
for (; startInclusive < endExclusive; startInclusive++) {
elements.add(BigInteger.valueOf(startInclusive));
}
return new Sequence(elements);
}
public static Sequence of(List<BigInteger> elements) {
return of(elements, false);
}
public static Sequence of(List<BigInteger> elements, boolean sync) {
return new Sequence(sync ? Collections.synchronizedList(elements) : elements);
}
public static Sequence empty() {
return empty(false);
}
public static Sequence empty(boolean sync) {
return of(new ArrayList<>(), sync);
}
}
FactorialCalculator.java
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
public final class FactorialCalculator {
private static final int CHUNK_SIZE = Runtime.getRuntime().availableProcessors();
public static BigInteger fact(int n) {
return fact(n, false);
}
public static BigInteger fact(int n, boolean parallel) {
if (n < 0) {
throw new IllegalArgumentException();
}
if (n <= 1) {
return BigInteger.ONE;
}
Sequence sequence = Sequence.range(1, n + 1);
if (!parallel) {
return sequence.product();
}
sequence = parallelCalculate(splitSequence(sequence, CHUNK_SIZE * 2));
while (sequence.size() > CHUNK_SIZE) {
sequence = parallelCalculate(splitSequence(sequence, CHUNK_SIZE));
}
return sequence.product(true);
}
private static List<Sequence> splitSequence(Sequence sequence, int chunkSize) {
final int size = sequence.size();
final List<Sequence> subSequences = new LinkedList<>();
int index = 0, targetIndex;
while (index < size) {
targetIndex = Math.min(index + chunkSize, size);
subSequences.add(sequence.subSequence(index, targetIndex, true));
index = targetIndex;
}
return subSequences;
}
private static Sequence parallelCalculate(List<Sequence> sequences) {
final Sequence result = Sequence.empty(true);
sequences.parallelStream().map(s -> s.product(true)).forEach(result::addLast);
return result;
}
}
Test :
public static void main(String[] args) {
// warm up
for (int i = 0; i < 100; i++) {
FactorialCalculator.fact(10000);
}
int n = 1000000;
long start = System.currentTimeMillis();
FactorialCalculator.fact(n, true);
long end = System.currentTimeMillis();
System.out.printf("Execution time = %d ms", end - start);
}
Result :
Execution time = 3066 ms
OS : Win 10 Pro 64-bit
CPU : Intel Core i7-4700HQ # 2.40GHz 2.40GHz
Recently, I've been attempting to create a program that prints prime numbers until a user-specified integer is achieved, the program itself including a "PrimeCheck" class, a "PrimeSieve" class of sorts, and a "Main" class:
public class PrimeCheck {
boolean result;
public PrimeCheck() {
result = true;
}
public boolean primeCheck (int num) {
int i, num1 = num - 1;
for (i = num1; i > 1; i--) {
if (num % i == 0) {
result = false;
}
}
return result;
}
}
import java.util.ArrayList;
public class PrimeSieve {
public PrimeSieve() {
}
PrimeCheck PCObj = new PrimeCheck();
ArrayList<Integer> primes = new ArrayList<Integer>();
public void primeSieve(int num) {
int[] arr = new int[num];
for (int i = 0; i < num; i++) {
arr[i] = i + 1;
if (PCObj.primeCheck(arr[i]) == true) {
primes.add(arr[i]);
}
}
for (int c = 0; c < primes.size(); c++) {
System.out.print(primes.get(c) + " ");
}
}
}
import java.util.Scanner;
public class PrimeSieveMain {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
PrimeSieve PSObj = new PrimeSieve();
System.out.println("Prime Sieve");
System.out.print("Limit: ");
int limit = input.nextInt();
PSObj.primeSieve(limit);
}
}
Pardon my inexperience, yet I cannot seem to locate the problem in this program.
Your problem is in the PrimeCheck class. That class has a state variable (a field) named result. State variables retain the value between calls, for as long as the object is "alive".
So as soon as you hit a number that is not prime, you set this result to false. That value is kept and never changes.
The result variable should be a local variable, not a state variable, and it should be set to true at the beginning of the method. This way it will start fresh every time.
Other notes:
There is really no point in the PrimeCheck class. It doesn't represent a real "entity", and the method can easily be added to the PrimeSieve class. Creating classes for different entities is a good practice, but I think in this case there is no point - it just has one function and that function doesn't depend on anything but its parameters.
If you meant to represent the Sieve of Eratosthenes then this is not the correct algorithm. This is the naive algorithm - it just tests each number individually and doesn't cross out multiples of previous primes as the real Sieve does.
The PrimeCheck has serveral design problems, the first is you designed the result variable as a member, and its only initialized to true upon construction, but updated with false in primeCheck(). Once it has returned false, it will return false on all subsequent calls.
Its also not necessary to design the result as a member, since the result is only related to the method primeCheck(), thus change it to return the value directly, eliminating the member:
public class PrimeCheck {
public boolean primeCheck (int num) {
for (int i = num - 1; i > 1; i--) {
if (num % i == 0) {
return false;
}
}
return true;
}
}
Since PrimeCheck now has no state left, the method could also be made static, making the PrimeCheck instance in your program superflous. You could just call the static method.
PrimeCheck is also terribly inefficient, due to several design choices - one is you start testing from (num - 1), but the most common divisors are the smallest numbers. So it would be more efficient to start testing from the lower end and work the loop upwards. The upper bound (num - 1) is also chosen poorly. The possible largest divisor for num is the square root of num, so the upper bound should be that.
When you get the number is not a prime:
public boolean primeCheck (int num) {
int i, num1 = num - 1;
for (i = num1; i > 1; i--) {
if (num % i == 0) {
result = false;
}
}
return result;
}
result become false, and never change, so I suggest this:
public boolean primeCheck (int num) {
result=true;
int i, num1 = num - 1;
for (i = num1; i > 1; i--) {
if (num % i == 0) {
result = false;
}
}
return result;
}
Before you start to determine prime, you should presume it is a prime
Not tested, just an idea
I'm working on the Project Euler 25. I worked out how to do Fibonacci and I'm using BigInteger. My program seems to be running for an infinite loop (or so I think). Could it be that it is taking a long time or is it actually going into infinite loop? Can someone point me in the correct direction so I can fix it?
import java.math.BigInteger;
public class Problem25 {
public static void main(String[] args) {
getTerm(0);
}
public static void getTerm(int start) {
BigInteger var = BigInteger.ZERO;
BigInteger var2 = BigInteger.valueOf(start);
int counter = 0;
while(true) {
BigInteger temp = var.add(var2);
var = var2;
var2 = temp;
counter++;
if(var.toString().length() > 1000) {
System.out.print(counter);
}
}
}
}
EDIT: Sorry people. I thought, I had break; but thanks for your responses.
You have no condition for terminating the loop:
while(true) { // << always true ;P
BigInteger temp = var.add(var2);
var = var2;
var2 = temp;
counter++;
if(var.toString().length() > 1000) {
System.out.print(counter);
}
}
So it is an infinite loop. You have two (or even more) options:
Specify in the while(statement) what is the condition to continue with the loop for another round.
Add some break; statement to stop the loop if a certain condition is evaluated as true.
getTerm(0);
Shouldn't this be getTerm(1);?
Also, MByD's answer is right; but this is also a critical problem. Without changing this, your program will never output.
1) Yes, you have an infinite loop. Put a break; statement right after your print().
2) Try looking for the first, oh, two-digit term. Or three-digit. Baby steps are good with a lot of the Project Euler problems.
3) Run it under a debugger, and watch what's happening. Combines well with 2).
You're calling getTerm(0), so initially var and var2 are both zero. Then you add var2 to var which is still zero, etc., so both var and var2 stay zero and you never make any progress. I think you meant getTerm(1), which should correctly generate the Fibonacci sequence.
And of course, you probably want to break out of the loop once you've found the answer.
Why don't you just print every value until a value with 1000 digits is found? There won't be that many anyway because the numbers grow with the golden ration on average.
And as stated elsewhere, add a stopcondition:
if(var.toString().length() > 1000) {
break;
}
Since true is always true, your loop will continue running forever unless you manually terminate it. Use break; for this. With your implementation, I think you should place it right after the line System.out.print(counter)
You can use:
while( !isGood() ) {
...
}
instead of
while(true) {
...
if ( isGood() ) {
break;
}
}
Here are 3 solutions that use the approach above (from slow to fast):
1) Generate all Fibonacci numbers until the condition is satisfied. Count the digits using division by 10. Time: 6625 ms
import java.math.BigInteger;
public class P25 {
final static int N = 1000;
public static void main(String[] args) {
int result = getTheFirstIndexHavingTheSpecifiedNumberOfDigits(N);
System.out.println(result);
}
// similar performance if you use an "aux" variable
private static int getTheFirstIndexHavingTheSpecifiedNumberOfDigits(int n) {
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
int i = 1;
while ( hasLessThanSpecifiedNumberOfDigits(a, n) ) {
b = b.add(a);
a = b.subtract(a);
i++;
}
return i;
}
private static boolean hasLessThanSpecifiedNumberOfDigits(BigInteger x, int n) {
return getNumberOfDigits(x) < n;
}
private static int getNumberOfDigits(BigInteger x) {
int numberOfDigits = 0 ;
while ( x.compareTo(BigInteger.ZERO) > 0 ) {
numberOfDigits++;
x = x.divide(BigInteger.TEN);
}
return numberOfDigits;
}
}
2) Generate all Fibonacci numbers until the condition is satisfied. Count the digits using the length of the string. Time: 783 ms
import java.math.BigInteger;
public class P25 {
final static int N = 1000;
public static void main(String[] args) {
int result = getTheFirstIndexHavingTheSpecifiedNumberOfDigits(N);
System.out.println(result);
}
private static int getTheFirstIndexHavingTheSpecifiedNumberOfDigits(int n) {
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
int i = 1;
while ( hasLessThanSpecifiedNumberOfDigits(a, n) ) {
b = b.add(a);
a = b.subtract(a);
i++;
}
return i;
}
private static boolean hasLessThanSpecifiedNumberOfDigits(BigInteger x, int n) {
return getNumberOfDigits(x) < n;
}
private static int getNumberOfDigits(BigInteger x) {
return x.toString().length();
}
}
3) Store the lowest BigInteger that has 1000 digits ( 10^999 ). Generate all Fibonacci numbers and compare them with the computed number. Time: 19 ms
import java.math.BigInteger;
public class P25 {
final static int N = 1000;
final static BigInteger MIN = BigInteger.TEN.pow(N-1);
public static void main(String[] args) {
int result = getTheFirstIndexHavingTheSpecifiedNumberOfDigits(N);
System.out.println(result);
}
private static int getTheFirstIndexHavingTheSpecifiedNumberOfDigits(int n) {
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
int i = 1;
while ( a.compareTo(MIN) < 0 ) {
b = b.add(a);
a = b.subtract(a);
i++;
}
return i;
}
}