2023/05/20

c語言函式指標的運用-梯形法計算面積

A+

一、梯形法簡介

在數學中,梯形法是一種計算曲線下面積的方法。它的原理是將曲線圖形分成許多小的梯形,並計算每個梯形的面積,最後將這些面積總和起來。這個方法在近似計算不可積分的曲線下面積時非常有用。

二、函式指標介紹

函式指標是C語言中的一個重要概念。它允許我們在函式中使用指標來操作和存取變數的地址。函式指標可以傳遞指標作為參數,並且可以在函數內部改變指標所指向的值。

三、梯形法計算面積的實現

1、積分運算函式

double calculatef(double (*f)(double, double), double a, double p, double q, int n)
{
    double area = f(a, p) + f(a, q);
    double h = (q - p) / n;
    for (double xi = p + h; xi < q; xi += h)
    {
        area += 2 * f(a, xi);
    }
    area *= (q - p);
    area /= (2 * n);
    return area;
}
這個函式使用矩形法則來進行積分,將給定區間分為多個小矩形,並計算每個矩形的面積後加總得到最終的積分值。接受的參數包括函式指標 f、積分區間 [p, q]、積分分割數量 n。

2、指定計算f1(x) or f2(x)的函式

double (*getOption(int option))(double, double)
{
    if (option == 1)
    {
        return f1;
    }
    else if (option == 2)
    {
        return f2;
    }
    return NULL;
}
這個函式根據給定的選項值,返回對應的函式指標,以便在 calculatef 中調用正確的函式。接受的參數是選項值 option。

4、計算f1(x) or f2(x)

double f1(double a, double x)
{
    return sqrt(a - x * x);
}

double f2(double a, double x)
{
    double f2 = (a * x * x * x + 7 * x) / sqrt(a + x);
    if (f2 < 0)
        f2 *= -1.0;
    return f2;
}
f1 函式:計算函數 f1 的值。它根據給定的參數 a 和 x,計算 sqrt(a - x * x)。
f2 函式:計算函數 f2 的值。它根據給定的參數 a 和 x,計算 (a * x * x * x + 7 * x) / sqrt(a + x)。如果計算結果小於 0,則將其乘以 -1.0。
可根據自己需求,自行修改程式碼改成自己想要計算的函數。

5、計算絕對值

double myabs(double a)
{
    if (a < 0)
        return -a;
    else
        return a;
}
計算給定數值的絕對值。如果參數 a 小於 0,則返回 -a,否則返回 a。

6、main函式

int main()
{
    int option;
    double a, p, q, err;
    while (scanf("%d", &option))
    {
        if (option == 0)
        {
            break;
        }
        scanf("%lf %lf %lf %lf", &a, &p, &q, &err);
        double (*Option)(double, double) = getOption(option);
        int n = 1;
        double prevarea = calculatef(Option, a, p, q, n);
        double currarea = calculatef(Option, a, p, q, 2 * n);
        n *= 2;
        double derr = pow(10, -err);
        while (myabs(prevarea - currarea) >= derr)
        {
            n *= 2;
            prevarea = currarea;
            currarea = calculatef(Option, a, p, q, n);
        }
        printf("%.12lf\n", currarea);
    }
    return 0;
}
在 main 函式中,程式首先從輸入中讀取選項值 option、參數 a、p、q 和 err。
a 表示函式中的常數,p 表示區間的起始位置,q 表示區間的終點位置,err 表示精確小數位數。
然後它使用 getOption 函式獲取對應的函式指標。
輸入整數1 代表計算 f1(x) 面積,2 代表計算 f2(x)面積。
接下來,使用數值積分的方法計算積分值,並根據給定的誤差要求調整積分的精度。
前一個計算結果跟目前的計算結果的差要小於10的-err次方,否則繼續計算,且切割度增加。
最後,輸出計算得到的積分值。
程式會持續讀取輸入,直到選項值為 0 時結束執行。輸入1或2,繼續新一輪計算。

四、結語

這是我的c語言作業的某一題,要求使用梯形法來計算面積。
通過這一題,展示了如何使用函式指標和梯形法來計算面積。
函式指標提供了一種更靈活和高效的方法來寫你的程式。
原本f1的計算要一個函數,f2的計算也要一個函數。
用了函式指標之後,結合起來只需要一個'calculatef'。
還增加了可讀性且方便維護。

五、完整程式碼

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double calculatef(double (*f)(double, double), double a, double p, double q, int n);
double (*getOption(int option))(double, double);
double f1(double a, double x);
double f2(double a, double x);
double myabs(double a);

int main()
{
    int option;
    double a, p, q, err;
    while (scanf("%d", &option))
    {
        if (option == 0)
        {
            break;
        }
        scanf("%lf %lf %lf %lf", &a, &p, &q, &err);
        double (*Option)(double, double) = getOption(option);
        int n = 1;
        double prevarea = calculatef(Option, a, p, q, n);
        double currarea = calculatef(Option, a, p, q, 2 * n);
        n *= 2;
        double derr = pow(10, -err);
        while (myabs(prevarea - currarea) >= derr)
        {
            n *= 2;
            prevarea = currarea;
            currarea = calculatef(Option, a, p, q, n);
        }
        printf("%.12lf\n", currarea);
    }
    return 0;
}

double calculatef(double (*f)(double, double), double a, double p, double q, int n)
{
    double area = f(a, p) + f(a, q);
    double h = (q - p) / n;
    for (double xi = p + h; xi < q; xi += h)
    {
        area += 2 * f(a, xi);
    }
    area *= (q - p);
    area /= (2 * n);
    return area;
}

double (*getOption(int option))(double, double)
{
    if (option == 1)
    {
        return f1;
    }
    else if (option == 2)
    {
        return f2;
    }
    return NULL;
}

double f1(double a, double x)
{
    return sqrt(a - x * x);
}

double f2(double a, double x)
{
    double f2 = (a * x * x * x + 7 * x) / sqrt(a + x);
    if (f2 < 0)
        f2 *= -1.0;
    return f2;
}

double myabs(double a)
{
    if (a < 0)
        return -a;
    else
        return a;
}

沒有留言:

張貼留言