The purpose of my assignment is to create a FOR loop that performs the circle method of getting pi and a WHILE loop that performs the Leibniz method for approximating Pi. I have no idea where to start for the Leibniz method because I don't understand what expression to put in the while loop to make it work. Please help me.
This method approximates pi by using a formula derived by Gottfried
Leibniz, also known as "the father of calculus." This method uses an
infinite series of additions and subtractions to approximate pi:
π/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + . . .
Notice that this approximates pi / 4. After the summation of the
terms, you need to multiply the value by 4 to arrive at the final
approximation. Analogous to the circle method, the more terms in the
series, the closer the approximation of pi: (Example)
Iterations Leibniz Method
1 4.000000000000
10 3.041839618929
100 3.131592903559
1000 3.140592653840
10000 3.141492653590
100000 3.141582653590
I have already completed the circle method for loop, and it works on its own. It's the while loop that the focus should be on.
double circle_pi(int rectangles)
{
double radius = 2.0;
long i;
long double width = radius / (long double)rectangles;
long double rect_area = 0.0;
long double midpoint, height;
midpoint = width / 2.0;
for(i = 1; i <= rectangles; i++)
{
height = sqrt((radius * radius) - (midpoint * midpoint));
midpoint = midpoint + width;
rect_area = rect_area + width * height;
}
return rect_area;
}
double leibniz_pi(int iterations)
{
while()
{
/* code */
}
return
}
This is my driver.c code to go with it. I cannot make changes to it.
double circle_pi(int rectangles); /* Calculates PI using a quarter circle */
double leibniz_pi(int iterations); /* Calculates PI using a series */
int main(void)
{
int i; /* loop counter */
/* Print out table header */
printf("Approximations for pi\n");
printf("Iterations Circle Method Leibniz Method\n");
printf("----------------------------------------------\n");
/* Print out values for each set of numbers */
for (i = 1; i <= 1000000; i *= 10)
{
/* Calculate PI with both methods */
double pi_circle = circle_pi(i);
double pi_leibniz = leibniz_pi(i);
/* Print the results of the calculations */
printf("%10i%20.12f%16.12f\n", i, pi_circle, pi_leibniz);
}
return 0; /* Return success to the OS */
}```
The Leibniz method subtracts and adds fractions with odd denominators alternately.
Thus, our code will look something like the following:
int count = 0;
int iters = 10000;
double pi_4 = 0;
while (count < iters) {
if (count % 2 == 0) {
// On "even" counts (where our fraction is 1/1, 1/5, 1/9..., add)
pi_4 += 1.0 / (1.0 + 2 * count);
else {
// On "odd" counts (where our fraction is 1/3, 1/7, 1/11..., subtract)
pi_4 -= 1.0 / (1.0 + 2 * count);
}
count++;
}
return 4 * pi_4;
Related
#include <stdio.h>
#include <math.h>
int main(void) {
// Set the initial value of pi to 0
double pi = 0.0;
// Set the initial value of the term to 1
double term = 1.0;
// Set the initial value of the divisor to 1
double divisor = 1.0;
// Print the table header
printf("%10s%25s\n", "Number of terms", "Approximation of pi");
// Calculate and print the approximations of pi
for (int i = 1; i <= 20; i++) {
pi += term / divisor;
printf("%10d%25.10f\n", i, pi*4.0);
term *= -1.0;
divisor += 2.0;
}
return 0;
}
I tried to correct the code but still can't get closer to the value as it is ask by my teacher in our assignment...
The Question is..
Calculate the value of π from the infinite series. Print a table that
shows the value of π approximated by one term of this series, by two terms, by three terms,
and so on. How many terms of this series do you have to use before you first get 3.14?
3.141? 3.1415? 3.14159?
How many terms of this series do you have to use before you first get 3.14? 3.141? 3.1415? 3.14159?
The details of "first get 3.14" are a bit unclear. Below attempts something like OP's goal and illustrates the slow convergence as computation time is proportional to the number of terms.
The high number of terms, each incurring round-off errors in the division and addition eventually render this computation too inaccurate for high term count.
int main(void) {
double pi_true = 3.1415926535897932384626433832795;
double threshold = 0.5;
int dp = 0;
// Set the initial value of pi to 0
double pi = 0.0;
// Set the initial value of the term to 1
double term = 1.0;
// Set the initial value of the divisor to 1
double divisor = 1.0;
// Print the table header
printf("%7s %12s %-25.16f\n", "", "", pi_true);
printf("%7s %12s %-25s\n", "", "# of terms", "Approximation of pi");
// Calculate and print the approximations of pi
for (long long i = 1; ; i++) {
pi += term / divisor;
double diff = fabs(4*pi - pi_true);
if (diff <= threshold) {
printf("%7.1e %12lld %-25.16f %-25.*f\n", diff, i, pi * 4.0, dp++, pi * 4.0);
fflush(stdout);
threshold /= 10;
if (4*pi == pi_true) {
break;
}
}
term *= -1.0;
divisor += 2.0;
}
puts("Done");
return 0;
}
Output
3.1415926535897931
# of terms Approximation of pi
4.7e-01 2 2.6666666666666670 3
5.0e-02 20 3.0916238066678399 3.1
5.0e-03 200 3.1365926848388161 3.14
5.0e-04 2000 3.1410926536210413 3.141
5.0e-05 20000 3.1415426535898248 3.1415
5.0e-06 200001 3.1415976535647618 3.14160
5.0e-07 2000001 3.1415931535894743 3.141593
5.0e-08 19999992 3.1415926035897974 3.1415926
5.0e-09 199984633 3.1415926585897931 3.14159266
5.0e-10 1993125509 3.1415926540897927 3.141592654
5.0e-11 19446391919 3.1415926536397927 3.1415926536
...
Ref 3.1415926535897931
On a 2nd attempt, perhaps this is closer to OP's goal
int main(void) {
double pi_true = 3.1415926535897932384626433832795;
double threshold_lo = 2.5;
double threshold_hi = 3.5;
double error_band = 0.5;
int dp = 0;
// Set the initial value of pi to 0
double pi = 0.0;
// Set the initial value of the term to 4
double term = 4.0;
// Set the initial value of the divisor to 1
double divisor = 1.0;
// Print the table header
printf("%12s %-25.16f\n", "", pi_true);
printf("%12s %-25s\n", "# of terms", "Approximation of pi");
// Calculate and print the approximations of pi
for (long long i = 1;; i++) {
pi += term / divisor;
if (pi > threshold_lo && pi < threshold_hi) {
printf("%12lld %-25.16f %-25.*f\n", i, pi, dp++, pi);
fflush(stdout);
char buf[100] = "3.1415926535897932384626433832795";
buf[dp + 2] = 0;
error_band /= 10.0;
double target = atof(buf);
threshold_lo = target - error_band;
threshold_hi = target + error_band;
}
term *= -1.0;
divisor += 2.0;
}
puts("Done");
return 0;
}
Output
3.1415926535897931
# of terms Approximation of pi
2 2.6666666666666670 3
12 3.0584027659273332 3.1
152 3.1350137774059244 3.14
916 3.1405009508583017 3.141
7010 3.1414500002381582 3.1415
130658 3.1415850000208838 3.14159
866860 3.1415915000009238 3.141592
9653464 3.1415925500000141 3.1415926
116423306 3.1415926450000007 3.14159265
919102060 3.1415926525000004 3.141592653
7234029994 3.1415926534500005 3.1415926535
I am writing a C program that will be able to accept an input value that dictates the number of iterations that will be used to estimate Pi.
For example, the number of points to be created as the number of iterations increases and the value of Pi also.
Here is the code I have so far:
#include <stdio.h>
#include <stdlib.h>
main()
{
const double pp = (double)RAND_MAX * RAND_MAX;
int innerPoint = 0, i, count;
printf("Enter the number of points:");
scanf("%d", &innerPoint);
for (i = 0; i < count; ++i){
float x = rand();
float y = rand();
if (x * x + y * y <= 1){
++innerPoint;
}
int ratio = 4 *(innerPoint/ i);
printf("Pi value is:", ratio);
}
}
Help fix my code as I'm facing program errors.
rand() returns an integer [0...RAND_MAX].
So something like:
float x = rand()*scale; // Scale is about 1.0/RAND_MAX
The quality of the Monte Carlo method is dependent on a good random number generator. rand() may not be that good, but let us assume it is a fair random number generator for this purpose.
The range of [0...RAND_MAX] is RAND_MAX+1 different values that should be distributed evenly from [0.0...1.0].
((float) rand())/RAND_MAX biases the end points 0.0 and 1.0 giving them twice the weight of others.
Consider instead [0.5, 1.5, 2.5, ... RAND_MAX + 0.5]/(RAND_MAX + 1).
RAND_MAX may exceed the precision of float so converting rand() or RAND_MAX, both int, to float can incurring rounding and further disturb the Monte Carlo method. Consider double.
#define RAND_MAX_P1 ((double)RAND_MAX + 1.0)
// float x = rand();
double x = ((double) rand() + 0.5)/RAND_MAX_P1;
x * x + y * y can also incur excessive rounding. C has hypot(x,y) for a better precision sqrt(x*x + y*y). Yet here, with small count, it likely makes no observable difference.
// if (x * x + y * y <= 1)
if (hypot(x, y <= 1.0))
I am sure it is not the best solution, but it should do the job and is similar to your code. Use a sample size of at least 10000 to get a value near PI.
As mentioned in the commenter: You should look at the data types of the return values functions give you.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
// Initialize random number generation
srand(time(NULL));
int samples = 10000;
int points_inside =0;
// Read integer - sample size (use at least 10000 to get near PI)
printf("Enter the number of points:");
scanf("%d", &samples);
for (int i = 0; i < samples; ++i){
// Get two numbers between 0 and 1
float x = (float) rand() / (float)RAND_MAX;
float y = (float) rand() / (float)RAND_MAX;
// Check if point is inside
if (x * x + y * y <= 1){
points_inside++;
}
// Calculate current ratio
float current_ratio = 4 * ((float) points_inside / (float) i);
printf("Current value of pi value is: %f \n", current_ratio);
}
}
The following full code could compare speed of fast inverse square root with 1/sqrt(). According to this sentence in wikipedia, (i.e. The algorithm was approximately four times faster than computing the square root with another method and calculating the reciprocal via floating point division.)
But here is why I am here: it is slower than 1/sqrt(). something wrong in my code? please.
#include <stdio.h>
#include <time.h>
#include <math.h>
float FastInvSqrt (float number);
int
main ()
{
float x = 1.0e+100;
int N = 100000000;
int i = 0;
clock_t start2 = clock ();
do
{
float z = 1.0 / sqrt (x);
i++;
}
while (i < N);
clock_t end2 = clock ();
double time2 = (end2 - start2) / (double) CLOCKS_PER_SEC;
printf ("1/sqrt() spends %13f sec.\n\n", time2);
i = 0;
clock_t start1 = clock ();
do
{
float y = FastInvSqrt (x);
i++;
}
while (i < N);
clock_t end1 = clock ();
double time1 = (end1 - start1) / (double) CLOCKS_PER_SEC;
printf ("FastInvSqrt() spends %f sec.\n\n", time1);
printf ("fast inverse square root is faster %f times than 1/sqrt().\n", time2/time1);
return 0;
}
float
FastInvSqrt (float x)
{
float xhalf = 0.5F * x;
int i = *(int *) &x; // store floating-point bits in integer
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
x = *(float *) &i; // convert new bits into float
x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
return x;
}
The result is as follows:
1/sqrt() spends 0.850000 sec.
FastInvSqrt() spends 0.960000 sec.
fast inverse square root is faster 0.885417 times than 1/sqrt().
A function that reduces the domain in which it computes with precision will have less computational complexity (meaning that it can be computed faster). This can be thought of as optimizing the computation of a function's shape for a subset of its definition, or like search algorithms which each are best for a particular kind of input (No Free Lunch theorem).
As such, using this function for inputs outside the interval [0, 1] (which I suppose it was optimized / designed for) means using it in the subset of inputs where its complexity is worse (higher) than other possibly specialized variants of functions that compute square roots.
The sqrt() function you are using from the library was itself (likely) also optimized, as it has pre-computed values in a sort of LUT (which act as initial guesses for further approximations); using such a more "general function" (meaning that it covers more of the domain and tries to efficientize it by precomputation, for example; or eliminating redundant computation, but that is limited; or maximizing data reuse at run-time) has its complexity limitations, because the more choices between which precomputation to use for an interval, the more decision overhead there is; so knowing at compile-time that all your inputs to sqrt are in the interval [0, 1] would help reduce the run-time decision overhead, as you would know ahead of time which specialized approximation function to use (or you could generate specialized functions for each interval of interest, at compile-time -> see meta-programming for this).
I correct my code as follows:
1. compute random number, instead of a fixed number.
2. count time consumption inside while loop and sum of it.
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
float FastInvSqrt (float number);
int
main ()
{
float x=0;
time_t t;
srand((unsigned) time(&t));
int N = 1000000;
int i = 0;
double sum_time2=0.0;
do
{
x=(float)(rand() % 10000)*0.22158;
clock_t start2 = clock ();
float z = 1.0 / sqrt (x);
clock_t end2 = clock ();
sum_time2=sum_time2+(end2-start2);
i++;
}
while (i < N);
printf ("1/sqrt() spends %13f sec.\n\n", sum_time2/(double)CLOCKS_PER_SEC);
double sum_time1=0.0;
i = 0;
do
{
x=(float)(rand() % 10000)*0.22158;
clock_t start1 = clock ();
float y = FastInvSqrt (x);
clock_t end1 = clock ();
sum_time1=sum_time1+(end1-start1);
i++;
}
while (i < N);
printf ("FastInvSqrt() spends %f sec.\n\n", sum_time1/(double)CLOCKS_PER_SEC);
printf ("fast inverse square root is faster %f times than 1/sqrt().\n", sum_time2/sum_time1);
return 0;
}
float
FastInvSqrt (float x)
{
float xhalf = 0.5F * x;
int i = *(int *) &x; // store floating-point bits in integer
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
x = *(float *) &i; // convert new bits into float
x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
return x;
}
but fast inverse square root still slower that 1/sqrt().
1/sqrt() spends 0.530000 sec.
FastInvSqrt() spends 0.540000 sec.
fast inverse square root is faster 0.981481 times than 1/sqrt().
I have a function that calculates the sin() of a radian angle. It takes two parameters, the value of the angle in radian and the terms. Just to make everything clear, this is how sin() is calculated:
sin(x) = x - (1/3! * X^3) + (1/5! * X^5) - (1/7! * X^7) + (1/9! * X^9) - ...
This is the function that do this calculation:
double sinx(double theta, int terms) //Theta is the angle x in radian
{
double result = 0;//this variable holds the value and it's updated with each term.
int i = 1;
int num = 3;
while(i <= terms-1)
{
if(i % 2 != 0){
result = result - ( (1.0/factorial(num)) * pow(theta, num) );
printf("if\n");//this is just for debugging
}
else if(i % 2 == 0){
result = result + ( (1.0/factorial(num)) * pow(theta, num) );
printf("else if\n");//this is for debugging too
}
printf("%lf\n", result);//debugging also
num = num + 2;
i = i + 1;
}
return theta + result; //this calculates the final term
}
The problem is the variable result's value doesn't change. Which also results in the final result not changing when using different number of terms.
Those are some outputs I get:
//with theta = 0.2 and terms = 6 ;;
if
-0.001333
else if
-0.001331
if
-0.001331
else if
-0.001331
if
-0.001331
Computed Sin<0.200000> = 0.198669. //this is the returned value. It's printed in the main
//with theta = 0.2 and terms = 7
if
-0.001333
else if
-0.001331
if
-0.001331
else if
-0.001331
if
-0.001331
else if
-0.001331
Computed Sin<0.200000> = 0.198669.
Any ideas?
Your code should be totally right. At least my calculator gives the same result.
If you change your printf("%lf\n", result); to printf("%.17f\n", result); you get this output:
if
-0.00133333333333333
else if
-0.00133066666666667
if
-0.00133066920634921
else if
-0.00133066920493827
if
-0.00133066920493878
else if
-0.00133066920493878
Now you can see, that it is still changing in every loop, but very little.
Really it converges fast so for double precision there is no difference between 6 and 7 terms. Here is the dump with better precision:
if
-0.00133333333333333350
else if
-0.00133066666666666680
if
-0.00133066920634920640
else if
-0.00133066920493827170
if
-0.00133066920493878470
Sin(0.2, 6) = 0.19866933079506122000
if
-0.00133333333333333350
else if
-0.00133066666666666680
if
-0.00133066920634920640
else if
-0.00133066920493827170
if
-0.00133066920493878470
else if
-0.00133066920493878450
Sin(0.2, 7) = 0.19866933079506122000
Everything looks correct here. The reason the result doesn't appear to change is to do with how quickly the Taylor series for sin converges for small angles. If you try with a bigger number say pi you should see the value updating slightly more often. You may also want to include something to limit theta from -pi to +pi as sin is a periodic function.
theta = mod(theta+pi, 2*pi) - pi
Including this restriction will alleviate the need for more terms if you start calculating values > pi or < -pi
If performance is important then you can reduce some of the calculations by removing repeats in calculating the factorials and large exponents
double sin(double theta, int terms = 7)
{
theta = mod(theta+pi, 2*pi) - pi;
double sum = x, term = x, fact = 3;
for (int i = 1; i < terms; i++)
{
term = -term * theta * theta /(fact * (fact - 1));
sum += term;
fact += 2;
}
return sum;
}
Your program as you have posted seems quite right IF you have your factorial written the right way. I have written factorial this way:
double factorial(int n) {
if(n <= 1) {
return 1.0;
}
else {
return n * factorial(n-1);
}
}
Try using this.
Using 0.785398 (approx. pi/4) and 10 terms, I get output 0.707107.
double d = sinx(0.785398, 10);
printf("%f\n", d); // prints 0.707107
Here are some runs:
printf("%.20f\n", sinx(3.1415926535897932, 100));
printf("%.20f\n", sinx(3.1415926535897932/2, 100));
printf("%.20f\n", sinx(3.1415926535897932/4, 100));
Outputs:
0.00000000000000044409
1.00000000000000000000
0.70710678118654746000
which seem accurate enough, given the pi used is only approximate.
What did you expect ?
The third term is
0.2^5/120 = 0.000002
if you show the first six decimals, and the next terms are yet smaller.
Side remark:
It is much more efficient and more accurate to compute a term from the previous, using the recurrence
T*= Z/(N*(N-1))
where Z= -X*X (and this way, the alternating signs are automatically handled).
It took me a while conceptual to grasp how to code a loop that would calculate a given series in which a factorial was used.
I coded it--then my teacher told us we had to use a single for loop. I can't seem to grasp how to do something like this. It doesn't make sense how you'd keep the running total of the products across several numbers.
Here is my code; which includes a nested for loop. I really appreciate any and all help.
int main() {
/*init variables*/
int N; //number of terms
float NUMER, DENOM = 1;
float FRAC, sum = 0, x;
/*asks user for value of N*/
printf("Input number of terms: ");
scanf("%i", &N);
/*asks user for value of x*/
printf("Input value of x: ");
scanf("%f", &x);
for (int n = 0; n <= N; n++) {
NUMER = (pow(x, n)); //calculates numerator
for (int fac = 1; fac <= n; fac++) { //calculates factorial using for loop
DENOM = n * fac;
}
if (DENOM <= 0)
printf("\n\nError, dividing by zero.\n\n"); //this is for debugging purposes; disregard
FRAC = NUMER / DENOM; //calculates fraction
sum += FRAC; //running sum of series
}
printf("\nSum of the series is %.1f\n\n", sum); //prints sum of series
return 0;
You want DENOM = n!, so you can just start with DENOM = 1
and update the value inside the loop:
DENOM = 1;
for (int n = 0; n <= N; n++) {
NUMER = (pow(x, n)); //calculates numerator
FRAC = NUMER / DENOM; //calculates fraction
sum += FRAC; //running sum of series
DENOM *= n+1;
}
Instead of computing x^n and n! each time through the outer loop, you can initialize
the quotient to 1.0 before the outer loop, then on each pass through the outer loop,
multiply by x/n to get the next term in the series. This will avoid the need
to call pow(x,n), and use an inner loop to calculate the factorial, each pass through
the outer loop.
If you think about what you would do if calculating a factorial by hand, I think you can figure out how to code this pretty easily.
Lets say you are trying to calculate 11!. Well, you would start at 11, and them multiply by 10. Now you have 110. Now multiply by 9. You have 990. Now multiply by 8...
As you can see, the 11, 10, 9, 8... series is what your for loop is going to be. Just keep your 'current answer' in a variable and keep multiplying it by the number provided by your for loop.
That seems...complicated. Terseness is or can be your friend :D
I don't think it needs to be much more complicated than:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char* argv[] )
{
double limit = 10 ; // how far do we want to go?
double x = 2 ; // some value for X
double xn = 1 ; // by definition, for all X, X^0 is 1
double nf = 1 ; // by convention, 0! is 1
double value = 0 ;
double sum = 0 ;
double n = 0 ;
while ( n < limit )
{
value = xn / nf ; // compute the next element of the series
sum += value ; // add that to the accumulator
xn *= x ; // compute the *next* value for X^n
nf *= (++n) ; // compute the *next* value for N!
}
return 0;
}
You get a more stable answer working the loop in reverse. Many infinite sums numerically come out better summing the smallest terms together first.
f(x,n) = x^0/0! + x^1/1! + x^2/2! + ... + x^n/n!
Let the sum be S(x,n) = x/n
Let the sum of the 2 last terms be S(x,n-1) = x/(n-1) + x/(n-1)*S(x,n)
Let the sum of the 3 last terms be S(x,n-2) = x/(n-2) + x/(n-2)*S(x,n-1)
...
Let the sum of the N last terms be S(x,1) = x/(1) + x/(1)*S(x,1)
double e(double x, unsigned n) {
double sum = 0.0;
while (n > 0) {
sum = x*(1 + sum)/n;
n--;
}
sum += 1.0; // The zero term
return sum;
}
Notice that even if n is large like 1000, and the mathematical answer < DBL_MAX, this loop does not run into floating point overflow so easily.
[edit] But if code must be done in a forward loop, the below calculates each term not as separate products that may overflow, but a unified computation.
double e_forward(double x, unsigned n) {
double sum = 1.0;
double term = 1.0;
for (unsigned i = 1; i <= n; i++) {
term *= x / i;
sum += term;
}
return sum;
}