Rev 173 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* Copyright: Ira W. Snyder* Start Date: 2005-11-28* End Date: 2005-11-29* License: Public Domain** Changelog Follows:* 2005-11-28* - Implement eval_euler() and eval_trapezoid().** 2005-11-29* - Implement eval_romberg() and eval_simpson().* - eval_trapezoid() was giving horrible results, fix it.**/#include <cmath>#include <cstdio>using namespace std;/*** The function given in the Project #5 Handout.* This is 1 + x^28** @param x the point at which to evaluate the function*/float func (float x){return 1.0 + pow (x, 28);}/*** Evaluate the integral of the function given, over the interval given,* using the Euler method.** @param a the lower bound of the integral* @param b the upper bound of the integral* @param n the number of intervals to use* @param f the function to evaluate*/float eval_euler (const float a, const float b, const int n, float(*f)(float)){const float h = (b - a) / n;float answer = 0.0, xi = 0.0;int i = 0;for (i=0; i<=n; i++){xi = a + (i * h);answer += f(xi);}return h * answer;}/*** Evaluate the integral of the function given, over the interval given,* using the trapezoid method.** This is derived from the book's pseudocode on Pg 207.** @param a the lower bound of the integral* @param b the upper bound of the integral* @param n the number of intervals to use* @param f the function to evaluate*/float eval_trapezoid (const float a, const float b, const int n, float(*f)(float)){const float h = (b - a) / n;float sum = 0.0;int i = 0;sum = (1.0/2.0) * (f(a) + f(b));for (i=1; i<=n-1; i++)sum += f(a + (i * h));return h * sum;}/*** Evaluate the integral of the function given, over the interval given,* using the Romberg method.** This is directly based on the pseudocode on Pg 223-224 of the textbook.** @param a the lower bound of the integral* @param b the upper bound of the integral* @param n the number of intervals to use* @param f the function to evaluate*/float eval_romberg (const float a, const float b, const int n, float(*f)(float)){float R[n+1][n+1];int i, j, k;float h, sum;/* Check for values that make us run wild, and refuse to run */if (n > 25){printf ("Cowardly refusing to run... You shouldn't need to use a\n""value of n > 25. Remember, the inner loop runs (2^n) - 1.\n");return 0.0;}h = b - a;R[0][0] = (h/2.0) * (f(a) + f(b));for (i=1; i<=n; i++){h = h/2.0;sum = 0.0;for (k=1; k<=(pow(2.0, i) - 1); k+=2)sum = sum + f(a + k * h);R[i][0] = (1.0/2.0) * R[i-1][0] + sum * h;for (j=1; j<=i; j++)R[i][j] = R[i][j-1] + (R[i][j-1] - R[i-1][j-1]) / (pow(4.0, j) - 1);}return R[n][n];}/*** Evaluate the integral of the function given, over the interval given,* using the Simpson method.** This is derived from the formula on Pg 237-238** @param a the lower bound of the integral* @param b the upper bound of the integral* @param n the number of intervals to use* @param f the function to evaluate*/float eval_simpson (const float a, const float b, const int n, float(*f)(float)){const float h = (b - a) / n;float sum1=0.0, sum2=0.0;int i;/* Get the first sum in the formula on Pg 238 */for (i=1, sum1=0.0; i<=n/2; i++)sum1 += f (a + (2 * i - 1) * h);sum1 *= 4;/* Get the second sum in the formula on Pg 238 */for (i=1, sum2=0.0; i<=(n-2)/2; i++)sum2 += f (a + 2 * i * h);sum2 *= 2;/* Add it all together, and return it */return (h / 3.0) * ((f(a) + f(b)) + sum1 + sum2);}int main (void){const float a = 0.0;const float b = 3.0;const float real = 3.0 + (pow(3.0, 29.0) / 29.0);float h, comp, abs, rel;int i, n;/* Euler Method Header */printf ("Euler's Method\n");printf ("i h Computed Abs Error Rel Error\n");printf ("====================================================================\n");/* Euler Method Table */for (i=1; i<=25; i++){h = pow(2.0, -i);n = (int)((b - a) / h);comp = eval_euler (a, b, n, &func);abs = fabs(real - comp);rel = fabs(real - comp) / fabs(real);printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);}/* Trapezoid Method Header */printf ("\n\nTrapezoid Method\n");printf ("i h Computed Abs Error Rel Error\n");printf ("====================================================================\n");/* Trapezoid Method Table */for (i=1; i<=25; i++){h = pow(2.0, -i);n = (int)((b - a) / h);comp = eval_trapezoid (a, b, n, &func);abs = fabs(real - comp);rel = fabs(real - comp) / fabs(real);printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);}/* Romberg Method Header */printf ("\n\nRomberg's Method\n");printf ("i h Computed Abs Error Rel Error\n");printf ("====================================================================\n");/* Romberg Method Table** NOTE: Don't go higher than 3 for this one, since the Romberg method's inner* loop runs (2^24) - 1 = 16777216 times at i=3 and* (2^48) - 1 = 2.81474 * 10^14 times at i = 4.*/for (i=1; i<=3; i++){h = pow(2.0, -i);n = (int)((b - a) / h);comp = eval_romberg (a, b, n, &func);abs = fabs(real - comp);rel = fabs(real - comp) / fabs(real);printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);}/* Simpson Method Header */printf ("\n\nSimpson's Method\n");printf ("i h Computed Abs Error Rel Error\n");printf ("====================================================================\n");/* Simpson Method Table */for (i=1; i<=25; i++){h = pow(2.0, -i);n = (int)((b - a) / h);comp = eval_simpson (a, b, n, &func);abs = fabs(real - comp);rel = fabs(real - comp) / fabs(real);printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);}return 0;}