Another interesting Algorithm for calculating factorial

Source: Internet
Author: User

The factorial of a positive integer n is the product of the First n positive integers. We usually need n-1 multiplication operations to calculate the exact value. Unlike the sum of the differential series, the N power of A, and so on, there is no super efficient algorithm for factorial. What we can do is to make some small optimizations.

Less multiplication times?
In high-precision operations, multiplication is much slower than addition or subtraction. Therefore, we need to reduce the number of multiplication operations. Next I will make a very simple transformation, so that the calculation of factorial only requires n/2 multiplication. Can you think of this algorithm on your own before proceeding?

We can convert the factorial of a number to the product of several square differences. For example, if I want to ask 9 !, I can write the product of the first nine positive integers as follows:
1*2*3*4*5*6*7*8*9
= (5-4) * (5-3) * (5-2) * (5-1) * 5*(5 + 1) * (5 + 2) * (5 + 3) * (5 + 4)
= (5-1) * (5 + 1) * (5-2) * (5 + 2) * (5-3) * (5 + 3) * (5-4) * (5 + 4) * 5
= (5 ^ 2-1 ^ 2) * (5 ^ 2-2 ^ 2) * (5 ^ 2-3 ^ 2) * (5 ^ 2-4 ^ 2) * 5
I noticed an interesting fact: the four square differences above are calculated as 24, 21, 16, and 9, respectively, the difference between them is exactly the continuous odd number (because n ^ 2 is equal to the sum of the First n positive odd numbers ). Therefore, we can use the initial number (n/2) ^ 2 to continuously subtract positive and odd numbers one by one to obtain all the square differences of N/Two, multiply them with n/2 multiplication. This algorithm is very simple to implement, and (when n is not large) only requires single-precision multiplication, but the number of multiplication times is greatly reduced. Suppose we already have a high-precision class, and calculate n! You only need the following sentence:
long h=n/2, q=h*h;
long r = (n&1)==1 ? 2*q*n : 2*q;
f = LargeInteger.create(r);
for(int d=1; d<n-2; d+=2)
   f = f.multiply(q-=d);

Less total operation times?
Extract factor 2 from factorial as much as possible. We can obtain another method to optimize factorial calculation. This is probably the fastest factorial algorithm that does not need to break down the prime factor.
Suppose we need to calculate 20 !, We can split 20 into the product of several groups of positive numbers:

1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20
= 1*3*5*7*9*11*13*15*17*19*2*4*6*8*10*12*14*16*18*20
= 1*3*5*7*9*11*13*15*17*19*1*2*3*4*5*6*7*8*9*10*2 ^ 10
= 1*3*5*7*9*11*13*15*17*19*1*3*5*7*9*2*4*6*8*10*2 ^ 10
= 1*3*5*7*9*11*13*15*17*19*1*3*5*7*9*1*2*3*4*5*2 ^ 15
= 1*3*5*7*9*11*13*15*17*19*1*3*5*7*9*1*3*5*2*4*2 ^ 15
= 1*3*5*7*9*11*13*15*17*19*1*3*5*7*9*1*3*5*1*2*2 ^ 17
= 1*3*5*7*9*11*13*15*17*19*1*3*5*7*9*1*3*5*1*2 ^ 18

The product of each group of odd numbers can be obtained after one multiplication, and all of them are multiplied by log (n) multiplication. The last 2 ^ 18 can also be calculated in two parts. There are still a lot of Optimizations in the real code, and recursion is also used to make the operation easier. You can find the split-recursive algorithm in the Link appended to this article.

Can it be faster?
Continuing to expand the above algorithm, we can think that if we break down the prime factor of each number and count the number of each quality factor, we can use the power of binary for multiple times, then multiply their results. Note that it is not really necessary to honestly break down the quality factor of each number. For each Prime Number X, we can quickly calculate the total number of prime factor X contained in the First n positive integers (remember how to calculate n! ). This algorithm is highly efficient and can meet the needs of most people.

Another strange factorial algorithm:
This algorithm may be the slowest of all named factorial algorithms (additive moessner algorithm). It repeatedly accumulates a series and calculates the prefix and, O (N ^ 3) addition operations will be performed in total. However, what is puzzling is, why can this simple program output the factorial of the First n positive integers?
a[0]:=1;
for i:=1 to n do
begin
   a[i]:=0;
   for j:=n downto 1 do
   begin
      for k:=1 to j do
         a[k]:=a[k]+a[k-1]
      write(a[i],' ');
   end;
end;

I found it when searching for related items online.Another interesting thing. Perform these two operations repeatedly for a series with all the values of 1 at the beginning: Accumulate the prefix and calculate the sum, and then use 1, 2, 3 ,... to generate a new sequence. A similar sequence operation method was first proposed by Alfred moessner. Here we may call it a moessner sequence. You will find that before the nth round of operation starts, the first number of the series is EXACTLY n! . Let's take a look at the example below:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15...
X 2x4 5x7 8 9x11 12 13 14 x...

2 4 5 7 8 9 11 12 13 14...
2 6 11 18 26 35 46 58 71 85...
X 6x18 26x46 58 71 X...

6 18 26 46 58 71...
6 24 50 96 154 225...
X 24x96 154 X...

24 96 154...
24 120 274...
X 120 X...

120...
.....

Of course, I was surprised when I found the association between the previous O (N ^ 3) program and the moessner series: In the previous program, if you output the series produced at the end of each I loop, you will find that the numbers output are exactly the ones we have crossed out in the problem, they are actually the first type of Stirling!
Why? What makes the factorial, the first Stirling number, and the moessner sequence associated with the O (N ^ 3) program? Yesterday, I thought about this problem for a day and finally figured it out. If we arrange the moessner series in this way, we will suddenly realize:


After careful observation, we will find that:
1. According to the definition of the moessner series, each number should be equal to the sum of the number on the left and the number in the upper left corner (this "Left" can skip several spaces ). For example, 35 = 9 + 26, 46 = 11 + 35. After a series of triangles are arranged, the number in the rightmost column of each triangle is the number to be divided. It will never be involved in the calculation of the rows below it.
2. Set a [n, I, j] To represent row I in the n-th triangle array from the leftRightFor the number of column J, A [n, I, j] = A [n-1, I-1, J] * n + A [n-1, I, j], for example, 274 = 50*5 + 24. If there is a blank position in the recurrence and there is still a number in the space on the left side, the number on the left should be used for population, for example, 18 = 4*4 + 2. For the last column of each triangle, this property is actually the recursive relationship of the first Stirling number. Therefore, the first Stirling number will appear in the moessner series.
3. In the first Stirling Number, S (n, 1) = n! That is, the number at the bottom of the nth triangle from the left is equal to N !. From the second nature above, this is also obvious.
The 4. O (N ^ 3) algorithm is actually drawing the above figure. At the end of each J loop, we obtain a sequence consisting of the number of J numbers starting from the left of each row in the I triangle. For example, when calculating the number of 5th triangles, the program first accumulates 1, 11, 46, 96,120,120, so that a [5] = 120, the first five numbers of the series are accumulated again to get 1, 12, 58,154,274, and thus calculate a [4] = 274.
The second property can be proved by mathematical induction using the first property, which is very simple and I will not say much. Now I try to write as few tedious details as possible, saving some time to review ancient Chinese.

Be honest,
Please indicate the source of the post.

View more:
Http://www.luschny.de/math/factorial/FastFactorialFunctions.htm
Http://www.luschny.de/math/factorial/index.html <---- giant ox, more than 20 types of factorial algorithm code!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.