Skip to content

Instantly share code, notes, and snippets.

@karthiks
Created July 18, 2014 10:26
Show Gist options
  • Save karthiks/caa70d39be1ee5180a35 to your computer and use it in GitHub Desktop.
Save karthiks/caa70d39be1ee5180a35 to your computer and use it in GitHub Desktop.
How to find Factorial of Numbers whose result is way toooo big for the native data structure to accommodate in any platform?
/*
* How to find Factorial of Numbers whose result is way toooo big for the native datastructure to accomodate in any platform?
* Source of Inspiration: CodeChef
* Discussion src: http://discuss.codechef.com/questions/7349/computing-factorials-of-a-huge-number-in-cc-a-tutorial
*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class BigFactorial {
public static void main(String args[] ) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int numberOfTestCases = Integer.parseInt(line);
String result[] = new String[numberOfTestCases];
for (int i = 0; i < numberOfTestCases; i++) {
int input = Integer.parseInt(br.readLine());
result[i] = factorial(input);
}
for(int i=0; i<numberOfTestCases; i++) {
System.out.println(result[i]);
}
// System.out.println(Long.MAX_VALUE);
// System.out.println("20! = 2432902008176640000");
// System.out.println("20! = " + factorial(20));
// System.out.println("21! = 51090942171709440000");
// System.out.println("21! = " + factorial(21));
// System.out.println("22! = 1124000727777607680000");
// System.out.println("22! = " + factorial(22));
}
private static String factorial(final int input) {
long fact = 1;
if(input <= 20) {
for(int i=2; i<=input; i++) {
fact *= i;
}
return fact + "";
}
String result = factorial(20) + "";
for(int i=21; i<=input; i++) {
List<String> interimResults = new ArrayList<>();
String strNum = String.valueOf(i);
for (int j=strNum.length()-1; j>=0; j--) {
final String reverse = reverse(multiply(result, strNum.charAt(j)) + zeros(strNum.length() - 1 - j));
interimResults.add(reverse);
}
result = sum(interimResults);
}
return result;
}
private static String reverse(final String str) {
return new StringBuilder(str).reverse().toString();
}
private static String sum(final List<String> interimResults) {
StringBuilder result = new StringBuilder("");
int longestStringLength = interimResults.get(interimResults.size() - 1).length(); //Last row in the interim must be the one..
int temp = 0, reminder = 0;
for (int i=0; i<longestStringLength; i++) {
ListIterator<String> iter = interimResults.listIterator();
int sum = 0;
while (iter.hasNext()) {
sum += intAt(iter.next(), i);
}
sum += temp;
if (sum > 9) {
temp = sum/10;
reminder = sum % 10;
} else {
temp = 0;
reminder = sum;
}
result.append(reminder);
}
if (temp > 0) result.append(temp);
return result.reverse().toString();
}
private static int intAt(final String str, int i) {
if(i >= str.length()) return 0;
return Integer.parseInt("" + str.charAt(i));
}
private static String zeros(final int j) {
if (j == 0) return "";
String result = "";
for (int i=0; i<j; i++) {
result += "0";
}
return result;
}
private static String multiply(final String result, final char cNum) {
String interimResult = "";
int temp = 0, reminder = 0;
for(int i=result.length()-1; i>=0 ; i--) {
int val1 = char2int(result.charAt(i));
int val2 = char2int(cNum);
int mult = (val1 * val2) + temp;
if (mult > 9) {
temp = mult/10;
reminder = mult % 10;
} else {
temp = 0;
reminder = mult;
}
interimResult = reminder + interimResult;
}
if (temp>0) interimResult = temp + interimResult;
return interimResult;
}
private static int char2int(char c) {
return Integer.parseInt("" + c);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment