more efficient Fibonacci for BigInteger - java

I am working on a class project to create a more efficient Fibonacci than the recursive version of Fib(n-1) + Fib(n-2). For this project I need to use BigInteger. So far I have had the idea to use a map to store the previous fib numbers.
public static BigInteger theBigFib(BigInteger n) {
Map<BigInteger, BigInteger> store = new TreeMap<BigInteger, BigInteger>();
if (n.intValue()<= 2){
return BigInteger.ONE;
}else if(store.containsKey(n)){
return store.get(n);
}else{
BigInteger one = new BigInteger("1");
BigInteger two = new BigInteger("2");
BigInteger val = theBigFib(n.subtract(one)).add(theBigFib(n.subtract(two)));
store.put(n,val);
return val;
}
}
I think that the map is storing more than it should be. I also think this line
BigInteger val = theBigFib(n.subtract(one)).add(theBigFib(n.subtract(two)));
is an issue. If anyone could shed some light on what i'm doing wrong or possible another solution to make it faster than the basic code.
Thanks!

You don't need all the previous BigIntegers, you just need the last 2.
Instead of a recursive solution you can use a loop.
public static BigInteger getFib(int n) {
BigInteger a = new BigInteger.ONE;
BigInteger b = new BigInteger.ONE;
if (n < 2) {
return a;
}
BigInteger c = null;
while (n-- >= 2) {
c = a.add(b);
a = b;
b = c;
}
return c;
}
If you want to store all the previous values, you can use an array instead.
static BigInteger []memo = new BigInteger[MAX];
public static BigInteger getFib(int n) {
if (n < 2) {
return new BigInteger("1");
}
if (memo[n] != null) {
return memo[n];
}
memo[n] = getFib(n - 1).add(getFib(n - 2));
return memo[n];
}
If you just want the nth Fib value fast and efficient.
You can use the matrix form of fibonacci.
A = 1 1
1 0
A^n = F(n + 1) F(n)
F(n) F(n - 1)
You can efficiently calculate A^n using Exponentiation by Squaring.

I believe the main issue in your code is that you create a new Map on each function call. Note that it's still local variable, despite that your method is static. So, you're guaranteed that the store.containsKey(n) condition never holds and your solution is not better than naive. I.e. it still has exponential complexity of n. More precisely, it takes about F(n) steps to get to the answer (basically because all "ones" that make up your answer are returned by some function call).
I'd suggest making the variable a static field instead of a local variable. Then number of calls should become linear instead of exponential and you will see a significant improvement. Other solutions include for loop with three variables which iteratively calculate Fibonacci numbers from 0, 1, 2 up to n-th and the best solutions I know involve matrix exponentiation or explicit formula with real numbers (which is bad for precision), but it's a question better suited for computer science StackExchange website, imho.

Related

How to calculate 2 to-the-power N where N is a very large number

I need to find 2 to-the-power N where N is a very large number (Java BigInteger type)
Java BigInteger Class has pow method but it takes only integer value as exponent.
So, I wrote a method as follows:
static BigInteger twoToThePower(BigInteger n)
{
BigInteger result = BigInteger.valueOf(1L);
while (n.compareTo(BigInteger.valueOf((long) Integer.MAX_VALUE)) > 0)
{
result = result.shiftLeft(Integer.MAX_VALUE);
n = n.subtract(BigInteger.valueOf((long) Integer.MAX_VALUE));
}
long k = n.longValue();
result = result.shiftLeft((int) k);
return result;
}
My code works fine, I am just sharing my idea and curious to know if there is any other better idea?
Thank you.
You cannot use BigInteger to store the result of your computation. From the javadoc :
BigInteger must support values in the range -2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE (exclusive) and may support values outside of that range.
This is the reason why the pow method takes an int. On my machine, BigInteger.ONE.shiftLeft(Integer.MAX_VALUE) throws a java.lang.ArithmeticException (message is "BigInteger would overflow supported range").
Emmanuel Lonca's answer is correct. But, by Manoj Banik's idea, I would like to share my idea too.
My code do the same thing as Manoj Banik's code in faster way. The idea is init the buffer, and put the bit 1 in to correct location. I using the shift left operator on 1 byte instead of shiftLeft method.
Here is my code:
static BigInteger twoToThePower(BigInteger n){
BigInteger eight = BigInteger.valueOf(8);
BigInteger[] devideResult = n.divideAndRemainder(eight);
BigInteger bufferSize = devideResult[0].add(BigInteger.ONE);
int offset = devideResult[1].intValue();
byte[] buffer = new byte[bufferSize.intValueExact()];
buffer[0] = (byte)(1 << offset);
return new BigInteger(1,buffer);
}
But it still slower than BigInteger.pow
Then, I found that class BigInteger has a method called setBit. It also accepts parameter type int like the pow method. Using this method is faster than BigInteger.pow.
The code can be:
static BigInteger twoToThePower(BigInteger n){
return BigInteger.ZERO.setBit(n.intValueExact());
}
Class BigInteger has a method called modPow also. But It need one more parameter. This means you should specify the modulus and your result should be smaller than this modulus. I did not do a performance test for modPow, but I think it should slower than the pow method.
By using repeated squaring you can achieve your goal. I've posted below sample code to understand the logic of repeated squaring.
static BigInteger pow(BigInteger base, BigInteger exponent) {
BigInteger result = BigInteger.ONE;
while (exponent.signum() > 0) {
if (exponent.testBit(0)) result = result.multiply(base);
base = base.multiply(base);
exponent = exponent.shiftRight(1);
}
return result;
}
An interesting question. Just to add a little more information to the fine accepted answer, examining the openjdk 8 source code for BigInteger reveals that the bits are stored in an array final int[] mag;. Since arrays can contain at most Integer.MAX_VALUE elements this immediately puts a theoretical bound on this particular implementation of BigInteger of 2(32 * Integer.MAX_VALUE). So even your method of repeated left-shifting can only exceed the size of an int by at most a factor of 32.
So, are you ready to produce your own implementation of BigInteger?

Infinite Fibonacci Sequence with Memoized in Java 8

Firstly, I'm a JavaScript programmer, and fairly new to Java8 and trying the new functional feature.
Since I expertise JS coding, I implemented my own JS lazy-functional library for proof of concept.
https://github.com/kenokabe/spacetime
Using the library, I could write Infinite sequence of Natural numbers and Fibonacci as below:
JavaScript
var spacetime = require('./spacetime');
var _ = spacetime.lazy();
var natural = _(function(n) //memoized automatically
{
return n; // Natural numbers is defined as the `n`th number becomes `n`
});
var natural10 = _(natural)
.take(10)
.compute(function(x)
{
console.log(x);
});
//wrap a recursive function to memoize
// must be at the definition in the same scope
var fib = _(function(n)
{
if (n <= 1)
return 1; // as the Fib definition in Math
else
return fib(n - 2) + fib(n - 1); // as the Fib definition in Math
});
var fib10 = _(fib)
.take(10)
.compute(function(x)
{
console.log(x);
});
Clear enough. The point is that I can define Natural/Fibonacci infinite sequence as the math definition as it is, then later compute the required part of the infinite sequence with lazy-evaluation.
So, now I wonder if I can do the same manner with Java8.
For natural sequence, I had post another Question here.
Infinite sequence of Natural numbers with Java8 generator
One of the way to define Natural sequence is to use iterator of Java8:
Java8
IntStream natural = IntStream.iterate(0, i -> i + 1);
natural
.limit(10)
.forEach(System.out::println);
I observe IntStream natural = IntStream.iterate(0, i -> i + 1); is a fair definition of natural numbers in math sense.
However, I wonder if it's possible to define it as I did before, that is,
JavaScript
var natural = _(function(n) //memoized automatically
{
return n; // Natural numbers is defined as the `n`th number becomes `n`
});
because this looks more concise. Unfortunately, the answers suggest it's probably not possible even we use generate.
In addition, IntStream.iterate does not fit for Fibonacci sequence.
I seek web to generate indefinite sequence of Fibonacci, the best results I found are
http://blog.informatech.cr/2013/05/08/memoized-fibonacci-numbers-with-java-8/
Java8
private static Map<Integer,Long> memo = new HashMap<>();
static {
memo.put(0,0L); //fibonacci(0)
memo.put(1,1L); //fibonacci(1)
}
//And for the inductive step all we have to do is redefine our Fibonacci function as follows:
public static long fibonacci(int x) {
return memo.computeIfAbsent(x, n -> fibonacci(n-1) + fibonacci(n-2));
}
This is not an infinite sequence (lazy Stream in Java8).
and
Providing Limit condition on Stream generation
Java8
Stream.generate(new Supplier<Long>() {
private long n1 = 1;
private long n2 = 2;
#Override
public Long get() {
long fibonacci = n1;
long n3 = n2 + n1;
n1 = n2;
n2 = n3;
return fibonacci;
}
}).limit(50).forEach(System.out::println);
This is an infinite sequence (lazy Stream in Java8), and you could say it's defined as Math.
However I do not like this implementation because, as you can see, there are many internal valuable to obtain the sequence such as n1 n2 n3 then fibonacci, accordingly the code structure is complicated and you need to control mutable state which is anti-functional manner - unlike the math definition, and probably this is not memoized.
So, here's my question. With Java8 Stream, is there any way to write a code to define the infinite sequence of fibonacci in concise math manner with memoization like
JavaScript
var fib = _(function(n)
{
if (n <= 1)
return 1; // as the Fib definition in Math
else
return fib(n - 2) + fib(n - 1); // as the Fib definition in Math
});
Thanks for your thought.
You can take your map-based memoized fibonacci(x) and make an infinite stream out of it like this:
LongStream fibs = IntStream.iterate(1, i->i+1).mapToLong(i -> fibonacci(i));
But the easiest way to make an infinite stream of fibonacci numbers is like this:
LongStream fibs = Stream.iterate(
new long[]{1, 1},
f -> new long[]{f[1], f[0] + f[1]}
).mapToLong(f -> f[0]);
As the article you linked to points out, "infinite" really means "until long overflows" which happens quickly. If you want to generate hundreds of fibonacci numbers, replace long with BigInteger:
Stream<BigInteger> bigFibs = Stream.iterate(
new BigInteger[]{BigInteger.ONE, BigInteger.ONE},
f -> new BigInteger[]{f[1], f[0].add(f[1])}
).map(f -> f[0]);

StackOverflowError computing factorial of a BigInteger?

I am trying to write a Java program to calculate factorial of a large number. It seems BigInteger is not able to hold such a large number.
The below is the (straightforward) code I wrote.
public static BigInteger getFactorial(BigInteger num) {
if (num.intValue() == 0) return BigInteger.valueOf(1);
if (num.intValue() == 1) return BigInteger.valueOf(1);
return num.multiply(getFactorial(num.subtract(BigInteger.valueOf(1))));
}
The maximum number the above program handles in 5022, after that the program throws a StackOverflowError. Are there any other ways to handle it?
The problem here looks like its a stack overflow from too much recursion (5000 recursive calls looks like about the right number of calls to blow out a Java call stack) and not a limitation of BigInteger. Rewriting the factorial function iteratively should fix this. For example:
public static BigInteger factorial(BigInteger n) {
BigInteger result = BigInteger.ONE;
while (!n.equals(BigInteger.ZERO)) {
result = result.multiply(n);
n = n.subtract(BigInteger.ONE);
}
return result;
}
Hope this helps!
The issue isn't BigInteger, it is your use of a recursive method call (getFactorial()).
Try this instead, an iterative algorithm:
public static BigInteger getFactorial(int num) {
BigInteger fact = BigInteger.valueOf(1);
for (int i = 1; i <= num; i++)
fact = fact.multiply(BigInteger.valueOf(i));
return fact;
}
The Guava libraries from Google have a highly optimized implementation of factorial that outputs BigIntegers. Check it out. (It does more balanced multiplies and optimizes away simple shifts.)
Naive implementations of factorial don't work out in real situations.
If you have a serious need, the best thing to do is to write a gamma function (or ln(gamma) function) that will work not only for integers but is also correct for decimal numbers. Memoize results so you don't have to keep repeating calculations using a WeakHashMap and you're in business.

Time complexity of the simple java code

How to determine time complexity of this code ? I guess that modPow method is the most "expensive ".
import java.math.BigInteger;
public class FermatOne
{
public static void main(String[] args)
{
BigInteger a = new BigInteger ("2");
BigInteger k = new BigInteger ("15");
BigInteger c = new BigInteger ("1");
int b = 332192810;
BigInteger n = new BigInteger ("2");
BigInteger power;
power = a.pow(b);
BigInteger exponent;
exponent = k.multiply(power);
BigInteger mod;
mod = exponent.add(c);
BigInteger result = n.modPow(exponent,mod);
System.out.println("Result is ==> " + result);
}
}
Well this particular code deterministically runs in O(1).
However, in more general terms for arbitrary variables, multiply() will run in O(nlog n) where n is the number of bits.
pow() method will run in O(log b) for small a and b. This is achieved by exponentiation by squaring. For larger values, the number of bits gets large (linearly) and so the multiplication takes more time. I'll leave it up to you to figure out the exact analysis.
I'm not 100% about the details about modPow(), but I suspect it runs similarly to pow() except with the extra mod at each step in the exponentiation by squaring. So it'll still be O(log b) multiplications with the added benefit that the number of bits is bounded by log m where m is the mod.
tskuzzy is correct.
But maybe reading between the lines a bit, and assuming this is a homework question, they probably want you to realize that there are several operations happening in this method with varying complexities. And then they probably want you to realize that the complexity of the overall method is the same as whatever the most complex operation is that happens in the method.

How to generate the discrete logarithm within java

I am looking for a short and simple algorithm for java that will help with finding the LOGa(x) in a cyclic group Z*p.
my method
would be log(prime_number, a, x)
this would compute the LOGaX in a cyclic group Z*p.
How would i go about doing this in an exhaustive search, or is there any simple way,
so I have gone with the exhaustive search, just to help me understand the discrete log.
//log(p,a,x) will return logaX in the cyclic group Z*p where p is
//prime and a is a generator
public static BigInteger log(BigInteger p,BigInteger a,BigInteger x){
boolean logFound = false;
Random r = new Random();
BigInteger k = new BigInteger(p.bitCount(),r);
while(!logFound){
if(a.modPow(k, p).equals(x)){
logFound = true;
}else{
k = new BigInteger(p.bitCount(),r);
}
}
//i dont think this is right
return a
}
So i want to return the LOGaX of the cyclic group Z*p, am i doing this here or what am i missing?
so i now return k and i am now doing a exhaustive search
#pauloEbermann i dont understand what i should do with k=k.multiply(a).mod(p)
my new code looks like this
//log(p,a,x) will return LOGaX in the cyclic group Z*p where p is
//prime and a is a generator
public static BigInteger log(BigInteger p,BigInteger a,BigInteger x){
boolean logFound = false;
Random r = new Random();
BigInteger k = BigInteger.ONE;
while(!logFound){
if(a.modPow(k, p).equals(x)){
logFound = true;
}else{
k = k.add(BigInteger.ONE);
}
}
return k;
}
with this test data
public static void main(String[] args) {
BigInteger p = new BigInteger("101");
BigInteger a = new BigInteger("3");
BigInteger x = new BigInteger("34");
System.out.println(log(p,a,x));
}
So this returns k = 99
this means that the log3(34) mod 101 is equal to 99 would i be right in saying this?
http://en.wikipedia.org/wiki/Discrete_logarithm lists 7 algorithms for computing the discrete logarithm.
For understanding the discrete logarithm itself, I would use pen and paper and construct a table of all powers of a generator of a small cyclic group. The logarithm is the inverse, so you already have your table for logarithms if you flip the columns.
The naive algorithm works like this, only that you do not store the table but simply loop and multiply by a until the current power matches x and output the number of multiplications plus done plus one as the logarithm of x base a.

Categories