This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calculate the factorial of an arbitrarily large number, showing all the digits
This question might be asked thousand times here. I am repeating my question with a modification. I want to calculate factorial of a large number (max range of the number=10^6). Generally we uses a for loop from i=1 to i=number and every time multiplying the old value to the new value. This is fine for small numbers but what if i have a large number? The range of for loop is increased now. Java primitive data type int, long can't handle the resultant large number. They simply overflows. Although i knew about BigInteger class, which can handle this large output but still for loop is not suiting better here for me. Can somebody please suggest me any tick, any hack to calculate factorial of a number? Below is the simple program which works fine for small number-
public long getFactorial(long number) {
long factorial = 1;
for (long i = 1; i <= number; ++i) {
factorial *= i;
}
return factorial;
}
Understand that the value is in the range of 105565708. It's going to take up about two megabytes of space, all by itself.
That said, Guava's BigIntegerMath.factorial(int) is good enough to handle it, and more importantly, it's actually been optimized for large factorials -- it'll do significantly better than a straightforward for loop. (Disclosure: I contribute to Guava...and wrote much of BigIntegerMath.factorial myself.)
That said, I wouldn't exactly call it fast -- my benchmarks indicate an average of 414ms for a factorial in that range -- but there isn't going to be a truly fast solution, not without extremely heavy-duty bignum libraries, and I wouldn't expect even those to be significantly faster.
That's if you need the exact value. If you can settle for the logarithm, then yeah, either use Apache's logGamma(n+1) to get ln(n!), or approximate it yourself:
double logFactorial = 0;
for (int i = 2; i <= n; i++) {
logFactorial += Math.log(i);
}
Some rounding error will probably accumulate, but it's supposed to be an approximation anyway.
You can use an approximation function called Stirling's Formula for such large values of n.
You can refer to my answer here for more details:
https://softwareengineering.stackexchange.com/questions/134968/number-of-combinations/134972#134972
Use the Gamma function. Gamma(i + 1) = i!
org.apache.commons.math.special provides it for Java.
What people typically do is to calculate log(Gamma(i+1)) and then work in log-space (multiplications become additions, etc.).
Here are some other methods to calculate the factorial quickly: http://www.luschny.de/math/factorial/FastFactorialFunctions.htm
You use BigInteger for factorial, and you still only need a long for i, the loop variable. i only has to go up to 1000000. What's the problem?
Related
This question already has answers here:
Large Numbers in Java
(6 answers)
Closed 5 years ago.
I've written a method that tests whether a number is prime or not. To maximise the range of numbers that the user can input, I wanted to use doubles. The issue is, after testing it on a very large prime, like 40 digits or so, my method returns false (I've already tested the logic with an int version, and it works just fine as far as I can tell).
Here is my code:
public static boolean isPrime(double number) {
double sqrt = Math.sqrt(number);
for(double i = 2; i<= sqrt; i++) {
if(number%i == 0) {
return false;
}
}
I know the reason it's not working at very high numbers is because of the accuracy error, but is there around this?
I know the reason it's not working at very high numbers is because of the accuracy error, but is there around this?
Yes. Use BigInteger.
Note that long would be better than double, since long can represent all integers up to 2^63 - 1 precisely. By contrast, with double you start losing precision at 2^53 + 1. However neither of these types are suitable for 40 (decimal) digit numbers.
BigInteger arithmetic is significantly slower, but the you will be able to go up to (at least) 2^Integer.MAX_VALUE ... provided that you have enough heap space.
I'm studying java programming by going through Computer Science at the Saylor academy's webpage. I got to the point where I'm learning about debugging programs in NetBeans, and there is a program that computes and prints the factorial of n (=1*2*3*...*n). The text says that there is a logical error in the program but nothing about where it is. And I can't seem to figure out where the logical error is.
Anyone who can help? The program code:
/** Compute the factorial of n */
public class Factorial {
// Print factorial of n
public static void main(String[] args) {
int n = 20;
int factorial = 1;
// n! = 1*2*3...*n
for (int i = 1; i <= n; i++) {
factorial *= i;
}
System.out.println("The Factorial of " + n + " is " + factorial);
}
}
20! is 2,432,902,008,176,640,000 (~ 2*10^18), much larger than the largest possible number that can be stored in an int, which is about 2 billion. This code will overflow and display an incorrect answer.
The correction to be made is to change the declaration of factorial from int to long.
The value of 20! is much bigger than the int type can store.
Use long instead of int
There might not be any Syntax Errors. But there is some error which is unknown to the compiler. Hence it hand overs this problem to OS and the OS immediately terminates the program. This is usually the case with C. Java was made even more powerful by introducing effective EXCEPTION HANDLING to overcome such type of problems i.e., logical errors.
As others have pointed out, the data type is your limitation in this case.
Should you wish to compute large maths, you should use a custom data type specifically suited to represent large numbers.
If you wish to learn about such an implementation, I highly recommend you read Paŭlo Ebermann's incredibly thorough answer to this StackOverflow question.
If you have no interest in how the implementation works but simple want to perform a large integer calculation, you can use Java's BigInteger data type.
Data type to hold a very large number say 1000 or more digits?
I need to find the factorial of a large number say 100000000.
My factorial program works nice for a smaller number.
long factorial(int x)
{
long fact=1;
if(x<0)
{
System.out.println("Incorrect input, enter a positive number");
fact=0;
}
if(x==0)
fact=1;
if(x>0)
{
fact=x;
fact=fact*factorial(x-1);
}
return fact;
}
You need a BigInteger. It can hold an arbitrarily large number.
But in your case 100000000! is such a huge number, that nothing can help.
You should use a log of gamma function, since gamma(n) = (n-1)! Far more efficient than your naive, student way of doing things. It'll be a double in that case, and the natural log will grow more slowly than the value does.
Recursion? Please. Your problem won't be the size of the value you pass back - you'll get too many stack frames and out of memory error long before that.
While BigInteger will theoretically handle such a value, you won't be able to compute it in practise.
First, your algorithm uses recursion, so you'd need 100.000.000 recursive calls of factorial. You'll get stack overflow far before computing the result. You'd have to modify your algorithm to avoid recursion (use a loop for example).
Second, the result will be huge. Using formulas for approximating factorials such as
log n! ~~ n log(n/e)
we can conclude that your number will have more than 750.000.000 digits. While with some luck you might be able to fit it into your memory, you will certainly not be able to compute the number in any reasonable time. Just imagine - you'll have to perform 100.000.000 multiplications with numbers that have hundreds of millions of digits.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Fast modulo 3 or division algorithm?
Everyone knows that modulo arithmetic can be a huge drawback on performance. Does anyone know of a good alternative for x%3 operations? I know that one exists for x%2, but I really need one for modulo 3 since I want to alternate between three buffers in a for loop.
Thanks!
Well instead of the usual "measure it" stuff an actual answer - because that stuff is actually real fun math. Although the compiler could and probably does this as well (at least modern optimizing c++ compilers, javac certainly won't and I've got no idea if the JVM does this) - so better check if it isn't already doing the work for you.
But still fun to know the theory behind the optimization: I'll use assembly because we need the higher 32bit word of a multiplication. The following is from Warren's book on bit twiddling:
n is the input integer we want the modulo from:
li M, 0x55555556 ; load magical number (2^32 + 2) / 3
mulhs q, M, n ; q = higher word of M * n; i.e. q = floor(M*n / 2^32)
shri t, n, 31 ; add 1 to q if it is negative
add q, q, t
Here q contains the divisor of n / 3 so we just compute the remainder as usual: r = n - q*3
The math is the interesting part - latex would be rather cool here:
q = Floor( (2^32+2)/ 3 * (n / 2^32) ) = Floor( n/3 + 2*n/(3*2^32) )
Now for n = 2^31-1 (largest n possible for signed 32bit integers) the error term is less than 1/3 (and non negative) which makes it quite easy to show that the result is indeed correct. For n = -2^31 we have the correction by 1 above and if you simplify that you'll see that the error term is always larger than -1/3 which means it holds for negative numbers as well.
I leave the proof with the error term bounds for the interested - it's not that hard.
If it's in a straight loop, no need to calculate a modulo. Hold a second int var that you reset every 3 steps.
int i, bn = 0;
for(i=0; i<whatever; i++) {
...
if(++bn == 3) bn = 0;
}
And that is not a premature optimisation, it's avoiding unecessary calculation.
EDIT: It was stated in OP that he was using a loop to switch between buffers, so my solution looks quite appropriate.
As for the downvote, if it was a mistake, no problem.
If 3 is known at compile time, then the compiler will generate the 'tricks' to do it as efficiently as possible. Modulo takes much longer when the divisor is unknown until run-time.
have been looking the page and lots of great people helping outhere so i have a Lab Assignment and i know i have to do a method concerning the fibonacci numbers to caclulate the number in the position n, but im not quite sure what do put inside the method i know is what i have to think about hope you can give and idea. Having trouble.(not asking to do the hw for me ok) Thank you.
Fibonacci numbers and complexity
Fibonacci numbers are defined recursively as follows:
F(n) = n, for n<=1
F(n) = F(n-1) + F(n-2) for n>1
Write the following methods to compute F(n):
a) A O(2n^n) method based on the recursive definition
b) A O(n) method that uses a loop
c) A O(1) method that uses the closed form solution – feel free to look for this formula on line.
Test all three methods using n = 10; 20; 50; 100; 1,000; 10,000; 100,000 and 1,000,000. If a particular algorithm and input combination does not return an answer in a reasonable amount of time, note that in your report (that is, don’t wait for hours (or worse) for your program to finish).
Well, to answer part c there is a constant time function that will calculate the nth fibonacci number. You can find the formula for it here: http://en.wikipedia.org/wiki/Fibonacci_number#Closed_form_expression
I assume "Hw" means homework, so no code I'm afraid.
a) O(2n) and O(n) are the same thing. Do you mean O(2^n)? This will happen if you use the recursive method without caching the results.
b) This is the "obvious" way to implement it, using a procedural implementation and remembering the last two numbers and using those to calculate the next one. In pseudo-code it would be something like loop { a, b = b, a+b; }
c) This won't work for all n unless you have infinite precision, and infinite precision isn't O(1). For example, when I use doubles fib(73) works out to be 806515533049395, but actually it is 806515533049393. The difference is due to rounding errors when working with floating point numbers.
And regarding the O(n) solution, if you are going to calculate up to fib(1000000) then a 64-bit integer isn't going to be anywhere near enough to store the result. You'll need to use BigIntegers. Adding two BigIntegers is not an O(1) operation, so the O(n) performance I mentioned before is too optimistic.