Article title: Algorithm analysis-a program used by aliens to calculate PI. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
I. source program
This article analyzes the following popular PI-based small program. The following program seems to have no idea at first, but you don't have to worry about it. after reading this article, you can basically understand it.
Program 1: a very good Pi computing program
Int a = 10000, B, c = 2800, d, e, f [2801], g;
Main (){
For (; B-c
F [B ++] = a/5;
For (; d = 0, g = c * 2; c-= 14, printf ("%. 4d", e + d/a), e = d %)
For (B = c; d + = f [B] * a, f [B] = d % -- g, d/= g --, -- B; d * = B );
}
II. mathematical formulas
Mathematicians have studied countless methods to calculate PI. the formula used in this program is as follows:
1 2 3 k
Pi = 2 + --- * (2 + --- * (2 + --- * (2 +... (2 + ---- * (2 + ...))...)))
3 5 7 2 k + 1
The reason why this formula can calculate PI is beyond the scope of this article.
The following is to analyze how the program implements this formula.
Let's first verify this formula:
Procedure 2: Pi Formula verification procedure
# Include "stdio. h"
Void main ()
{
Float pi = 2;
Int I;
For (I = 100; I> = 1; I --)
Pi = pi * (float) I/(2 * I + 1) + 2;
Printf ("% f \ n", pi );
Getchar ();
}
The result of the above procedure is 3.141593.
3. program development
Before formally analyzing the program, we need to expand Program 1. We can see that all programs use the for loop to complete the computation. this can make the program short, but it is difficult to understand. According to the running sequence of the for loop, we can expand it into the following while loop program:
Program 3: the program after converting for to while
Int a = 10000, B, c = 2800, d, e, f [2801], g;
Main (){
Int I;
For (I = 0; I F [I] = a/5;
While (c! = 0)
{
D = 0;
G = c * 2;
B = c;
While (1)
{
D = d + f [B] *;
G --;
F [B] = d % g;
D = d/g;
G --;
B --;
If (B = 0) break;
D = d * B;
}
C = C-14;
Printf ("%. 4d", e + d/);
E = d %;
}
}
Note:
For ([1]; [2]; [3]) {[4];}
The running sequence is [1], [2], [4], [3]. If there is a comma operator, for example, d = 0, g = c * 2, run d = 0 first, then run g = c * 2, and the final result is the value of the last expression, that is, c * 2 here.
Next we will analyze the expanded program.
IV. program analysis
To calculate an infinite PI, we need to run the above iteration formula countless times, and each score is completely accurate, which is naturally impossible in the computer. The basic idea is to iterate multiple times and each score is accurate enough to calculate the first n bits of PI. The above code calculates 800 bits, and the iteration formula iterates 2800 times in total.
Int a = 10000, B, c = 2800, d, e, f [2801], g;
In this sentence, 2800 is the number of iterations.
Because float or double is far from accurate enough, the program uses the integer type (actually a long integer) and the segmentation operation (4 bits each time ). The output statement printf ("%. 4d ", e + d/a); where %. 4 is to calculate the 4-bit output, we see that c each reduce 14 (c = C-14;), and c's initial size is 2800, so a total of 200 segment operation, and 4 bits are output each time, so a total of 800 bits are output.
Because integer calculation is used, it is necessary to multiply a coefficient. in this program, the coefficient is 1000, that is, the formula is as follows:
1 2 3 k
1000 * pi = 2 k + --- * (2 k + --- * (2 k + --- * (2 k +... (2 k + ---- * (2 k + ...))...)))
3 5 7 2 k + 1
2 K indicates 2000, that is, the data after f [2801] array initialization, a = 10000, a/5 = 2000, so the following program assigns each element in f to 2000:
For (I = 0; I F [I] = a/5;
You may wonder why a constant is stored in an array. please continue.
Let's first track the running of the program:
While (c! = 0) suppose this is the first operation, c = 2800, which is the number of iterations.
{
D = 0;
G = c * 2; Here g is used for molecules in k/(2 k + 1)
B = c; here B is used for molecules in k/(2 k + 1)
While (1)
{
D = d + f [B] * a; all values in f are 2000. here, the coefficient is increased by a = 10000 times.
The purpose of doing so will be introduced later. you can see that the output is d/a, so this does not affect
Computing
G --;
F [B] = d % g; ignore this line first
D = d/g; the first running g is 2*2799 + 1. you can see that g is used as the denominator.
G --;
B --;
If (B = 0) break;
D = d * B; here, B is 2799. we can see that d is a molecule.
}
C = C-14;
Printf ("%. 4d", e + d/);
E = d %;
}
Just take a rough look at the above program and we will probably know that it is indeed using the iteration formula to calculate Pi, however, I don't know whether you have understood the usefulness of the f array till now. If you do not understand, continue reading.
D = d/g. the purpose of this line is divided by 2 k + 1. we know that the reason why the program cannot be accurately calculated is the division. That is, when floating point numbers are used, the answer is not accurate enough. Therefore, it is impossible to directly calculate the 800-bit Pi. So where are the inaccurate components? Obviously: the remainder d % g. The program uses the f array to store this error and use it for the next calculation. Now you should also know why d = d + f [B] * a; it is necessary to multiply a in the middle. After the numerator is expanded, the error can be accurately calculated.
If d does not multiply the coefficient of 10000, its value is 2000, then run d = d/g; then it is 2000/(2*2799 + 1 ), the division answer for this integer is 0, and it cannot be iterated at all.
Now we know that the program stores the remainder as a parameter for the next iteration. so why can we make the next iteration result
What about the next number?
This is actually very similar to division on paper:
We can find that when division is performed, we usually expand the remainder before calculation. in f, since the remainder is stored, f [B] *; then the remainder is expanded by a times, and the arbitrary precision can be calculated after such a loop.
It should be noted that, in fact, the calculated d is not necessarily only 4 digits. for example, during the first computation, the value of d is 31415926, and when the output is 4 digits, store the values of the lower four bits in the middle of e, e = d % a, that is, 5926.
Finally, this c = C-14 is not easy to understand. In fact, without this statement, the program still calculates it correctly. It is only because, no matter how accurate the score is, the accuracy of Pi can only reach 2800.
You can try the program in the following format:
For (I = 0; I <800; I ++)
{
D = 0;
G = c * 2;
B = c;
While (1)
{
D = d + f [B] *;
G --;
F [B] = d % g;
D = d/g;
G --;
B --;
If (B = 0) break;
D = d * B;
}
// C = C-14; don't say this.
Printf ("%. 4d", e + d/);
E = d %;
}
The final answer is still correct.
However, we can see that the number of inner loops is c, that is, the number of iterations is c. The number of iterations is reduced by 14 each time the subsequent digits are calculated, without affecting the accuracy. Why? I did not study it. In addition, the functions of e + d/a and e = d/a are considered by the readers themselves.
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.