Abstract: This article uses an algorithm idea that is almost the same as "computing of big data factorial from entry to entry". It is different from the previous article in this article, the program given in this article uses an array element to represent 4-or 9-bit 10-digit numbers, which makes the calculation faster and saves more memory. This article provides two factorial functions. The program code is concise and the speed is not slow. The first program requires about 10 thousand KB of memory for calculating the 0.86 factorial, and seconds for the GB notebook. In "big number factorial calculation from entry to entry-one of the entry points", we provide a program for calculating factorial, which uses char arrays to store large numbers, one element represents a one-digit decimal number. During calculation, a single Multiplication can calculate the product of one digit and one integer. This algorithm has simple and intuitive advantages, but its disadvantages are obvious, the speed is not fast, and the memory usage is also large. This article will provide a modified program to effectively overcome these shortcomings. Anyone who has learned 80x8086/8088 Assembly knows that of the CPU can multiply the number of two 16 bits and the result is 32 bits, 80386 and the next 32-bit CPU can multiply the two 32-bit numbers and the result is 64-bit (the following bit is written ). 16-bit CPUs, such as 8086 CPUs, have been completely eliminated. This is not to be discussed. In the 32-bit C language compiler, the unsigned long (DWORD) variable can represent a 32bit integer, And the unsigned short (Word) variable can represent a 16bit integer. The result is completely stored in an unsigned number after the number is multiplied by less than 65535.

Long variable. In addition, many 32-bit compilers also provide 64-bit integer types (for example, in VC, unsigned _ int64 can represent a 64-bit integer. in GCC, long

Long can be a 64-bit integer ). Similarly, if the number is multiplied by a number of less than 4 billion, the result can be stored with an unsigned _ int64 variable. It is a waste of time to let a CPU with the ability to calculate two 32-bit multiplication at a time to calculate only one 10-digit number and one integer multiplication at a time. Next, we propose two methods to represent and calculate large numbers. Method 1: Use a Word Array to represent a large number, and use a DWORD variable to represent the product of two word variables. Each element of the array represents a four-digit decimal number. During the operation, the last element of the number is multiplied by the current Multiplier and the carry value is added. The lower four digits of the sum still exist in the original position, and the higher digits carry forward. When the multiplier I is less than 0.42 million, the product plus carry can be expressed by a DWORD variable, so this program can calculate the factorial up to 0.42 million. When the factorial of 0.42 million is calculated, memory usage is less than 1.1 MB. As for the speed, it takes about 1000/10000/0.015 seconds to calculate the factorial of 0.86 on a GB computer.

# Include "stdlib. H "# include" stdio. H "# include" math. H "# define PI 3.1415926535897932384626433832795 # define rad 10000 typedef unsigned long DWORD; typedef unsigned short word; // use the Stirling formula to estimate the result length, which is slightly larger than DWORD calcresultlen (dword n, DWORD rad) {double r = 0.5 * log (2 * PI) + (n + 0.5) * log (N)-N; Return (DWORD) (R/log (RAD) + 2);} void calcfac1 (dword n) {dword I, carry, prod, Len; word * buff, * phead, * ptail, * P; if (n = 0) {P Rintf ("% d! = 1 ", n); return;} // --- calculate and allocate the required storage space Len = calcresultlen (n, rad); buff = (word *) malloc (sizeof (Word) * Len); If (buff = NULL) return; // the following code calculates n! Phead = ptail = buff + len-1; For (* ptail = 1, I = 2; I <= N; I ++) {for (carry = 0, P = ptail; p> = phead; p --) {prod = (DWORD) (* P) * I + carry; * P = (Word) (prod % rad ); carry = Prod/rad;} while (carry> 0) {phead --; * phead = (Word) (carry % rad); carry/= rad ;}} // display the calculation result printf ("% d! = % D ", N, * phead); For (P = phead + 1; P <= ptail; P ++) printf (" % 04d ", * P ); printf ("/N"); free (buff); // release allocated memory} int main (INT argc, char * argv []) {dword n; printf ("Please input N:"); scanf ("% d", & N); calcfac1 (n); Return 0 ;}

Method 2: Use a DWORD array to represent a large number, and use unsigned _ int64 to represent the product of two DWORD variables. Each element of the array represents a nine-digit decimal number. During the operation, the number is multiplied by the current Multiplier I (I = 1 .. n) plus the carry of the last time, the 9-bit lower digits of the sum still exist in the original position, and the number of carry forward digits in the descending order of the sum still exist. In terms of algorithms, this program can calculate a factorial of 4 billion. In actual calculation, it is limited by the memory size. As for speed, it is slower than the previous program because it is unsigned.

_ Int64 division is slow. We will provide a solution in the next article. below is the code that uses this method to calculate factorial.

# Define ten9 1000000000 void calcfac2 (dword n) {DWORD * buff, * phead, * ptail, * P; dword t, I, Len; uint64 carry, prod; if (n = 0) {printf ("% d! = 1 ", n); return;} // --- calculate and allocate the required bucket T = gettickcount (); Len = calcresultlen (n, ten9 ); buff = (DWORD *) malloc (sizeof (DWORD) * Len); If (buff = NULL) return; // the following code calculates n! Phead = ptail = buff + len-1; For (* ptail = 1, I = 2; I <= N; I ++) {for (carry = 0, P = ptail; p> = phead; p --) {prod = (uint64) (* P) * (uint64) I + carry; * P = (DWORD) (prod % ten9 ); carry = Prod/ten9;} while (carry> 0) {phead --; * phead = (DWORD) (carry % ten9); carry/= ten9 ;}} T = gettickcount ()-T; // display the calculated result printf ("It take % d MS/N", T); printf ("% d! = % D ", N, * phead); For (P = phead + 1; P <= ptail; P ++) printf (" % 09d ", * P ); printf ("/N"); free (buff); // release allocated memory}

Liangbch@263.net, copyright, reprinted please indicate the source.