Recursive function to calculate combination and factorial - java

I am using the following two functions to calculate factorials and combinations.
public static long Factorial(long n)
{
if (n == 0)
return 1;
else
return n * Factorial(n-1);
}
public static long combinations (long n, long k)
{
return Factorial(n)/(Factorial(k) * Factorial(n - k));
}
I am testing it using:
long test = combinations((long)21, (long)13);
It seems to work for small numbers such as 5,2. But if I try 21,13, I get incorrect answers (negatives or 0).
Would anyone know what is happening here?

The maximum value of long in java is 2^63.
That will safely take you up to the factorial of 20. However, factorial of 21 comes to around 2^65, so you are exceeding the maximum value that can be represented.
See this question for a discussion about what happens in java if you perform a multiplication that results in an overflow.

This is mainly because of overflow from long (64bit signed). You can look up BigDecimal or BigInteger for use in this case.

As other users have said long can't hold Factorial(21). I rewrote your Factorial method using BigInteger and it seems to work, although you have to pass a BigInteger in as the parameter.
public static BigInteger Factorial(BigInteger n)
{
if (n.equals(BigInteger.ZERO))
return BigInteger.ONE;
else
return n.multiply(Factorial(n.subtract(BigInteger.ONE)));
}
Then rewrite your combinations method using BigInteger:
public static BigInteger combinations (BigInteger n, BigInteger k)
{
return Factorial(n).divide(Factorial(k).multiply(Factorial(n.subtract(k))));
}
In the main method I called the combinations method like this
System.out.print(combinations(new BigInteger("21"), new BigInteger("13")));

Related

How to calculate (a^b^c^d) mod 10^9+7?

i tried using this.
import java.io.*; // for handling input/output
import java.util.*; // contains Collections framework
// don't change the name of this class
// you can add inner classes if needed
class Main {
public static void main (String[] args) {
Scanner s=new Scanner(System.in);
int m=1000000007;
int a=s.nextInt();
int b=s.nextInt();
int c=s.nextInt();
int d=s.nextInt();
long temp1=power(c,d)%m;
long temp2= power(b,temp1)%m;
long result=power(a,temp2)%m;
System.out.println(result);
}
public static long power(int x, long n){
int m=1000000007;
if(n==0){
return 1;
}
if(n==1){
return x;
}
if(n%2==0){
return (power(x,n/2)*power(x,n/2))%m;
}else {
return ((power(x,n/2)*power(x,n/2))%m * x)%m;
}
}
}
but problem is when i increase size of a b c d then its showing TLE.
like for a=2 b=2 c=2 d=2 its giving output 65536 but when i take a=12 b=12 c=12 d=12 output should be 322269119 but using this it is showing Time limit exceed error. anyone can explain how to do this type of qurstion where it said that output value will be large so print is after doing mod 10^9+7.
Edit: a b c d values can be different.
The TLE is due to power recursively calling itself twice per invocation, so it expands to a full binary tree of calls (size: n) instead of into a nice linear chain of calls (length: log(n)) which is how Exponentiation by Squaring is supposed to work. In other words, it's exponentially slower than it needs to be, and for a very boring reason. Easy fix:
public static long power(int x, long n){
int m=1000000007;
if(n==0){
return 1;
}
if(n==1){
return x;
}
long p = power(x,n/2);
if(n%2==0){
return p * p % m;
}else {
return (p * p % m) * x % m;
}
}
But there is also a "math bug" in your program: abcd mod n is not equivalent to a^(b^(c^d mod n) mod n) mod n. Modular addition and multiplication work that way, but exponentiation has a different kind of periodicity.
Just using big integers naively is not sufficient, 12^12^12 would be a 4TB BigInteger, even on a computer that could handle that, computing or using such a physically large number would just take too long. But you can use Euler's theorem, and compute 12^12^12 mod φ(n). 12^12 is no big deal it even fits in a long, then 12 to the power of that long can be a modexp again but modulo φ(1E9+7) which is 1E9+6. For slightly larger c and d, c^d can also be computed as a BigInteger, as long as it isn't too big.
When c or d are so large that c^d is a problem even with BigIntegers, you can use more tricks to compute b^c^d mod φ(n) without the "full" c^d. Unfortunately Euler's theorem is not applicable to the "inner" exponentiation because the GCD of the modulus and the base may not be 1 (and isn't 1 in the example with the twelves), but there is a more complex expression that works in that case.

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?

more efficient Fibonacci for BigInteger

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.

Why does my recursion program print a negative number?

My code for whatever reason is printing out a negative number when i run it with certain numbers(17). It is supposed to find the factorial of a number and print it out however clearly that isn't happening.
package recursion;
public class recursion_1 {
public static void main(String[] args) {
int x = factorial(17);
System.out.println(x);
}
public static int factorial(int N) {
if (N == 1) return 1;
return N * factorial(N-1);
}
}
You're encountering integer overflow.
factorial(17) is 3.5568743e+14, which is well beyond the bounds of int. When an integer operation overflows, it can end up negative. For example:
int x = Integer.MAX_VALUE;
x++;
System.out.println(x); // Very large negative number
In your case, you'll have overflowed several times - even if the result were positive, it still wouldn't be right.
If you need integers in the range of [-263, 263-1] you can use long instead of int. If you want arbitrarily large integers, use BigInteger instead. For example:
// Note rename of parameter to follow Java conventions
public static BigInteger factorial(int n) {
return factorial(BigInteger.valueOf(n));
}
public static BigInteger factorial(BigInteger n) {
if (n.equals(BigInteger.ONE)) {
return BigInteger.ONE;
}
return n.multiply(n.subtract(BigInteger.ONE));
}
Factorials grow quickly in value, such that 17! (355687428096000) too large to fit in an int, causing overflow and the negative number.
Return a long from factorial, so that when the multiplication occurs, it won't overflow (yet). You'll need to declare x as a long also. Note that this will only postpone the problem, because sufficiently high values of N will overflow a long too. If necessary, use BigIntegers.
This is because the maximum value an int can have is 2,147,483,647. 17! exceeds this number. If an integer is assigned a number bigger than its maximum size, it starts counting up from -2,147,483,647.
2,147,483,647 + 1 = -12,147,483,647
Try a long or BigDecimal instead =)

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.

Categories