在C中实现梯形数值积分

时间:2014-08-04 17:47:03

标签: c numerical-methods

我尝试使用此公式使用梯形近似来实现数值积分: formel

我的问题是我不知道如何正确实现这一点。为了测试,我编写了一个文件,22050双值都等于2,如:

....................
    value =2.0;
    for ( index = 0 ; index < 22050;index++){           
            fwrite(&value,sizeof(double),1,inp2);
        }

保持问题简单,说我想要每100个样本的积分值:

 X Area                integral value 
0-100               should be  200  
100-200             should be  200
.....                ...........
22000-22050         should be  100

要做到这一点,我已经编写了一个应该这样做的程序,但4387950 100 samples得到的结果是我的代码:

..............................
    // opening the files 

double* inputData= NULL;
unsigned int N = 100;
double h= 0.0;
unsigned int index= 0;
FILE* inputFile=NULL;
double value =0.0;
int i =0,j=0;


    inputFile = fopen("sinusD","rb");
    outputFile=fopen("Trapez","wb+");
    if( inputFile==NULL || outputFile==NULL){
        printf("Couldn't open the files \n");
        return -1;
    }
    inputData = (double*) malloc(sizeof(double)*N);

    h=22050/2;
    while((i = fread(inputData,sizeof(double),N,inputFile))==N){
        value += inputData[0] +inputData[N];
        for(index=1;index<N;index++){
            value+=(2*inputData[index]);
        }
        value *=h;
        fprintf(outputFile,"%lf ",value);
        value =0;

    }
    if(i!=0){
        value = 0;
        i=-i;
        printf("i value %i\n", i);
        fseek(inputFile,i*sizeof(double),SEEK_END);
        fread(inputData,sizeof(double),i,inputFile);
            for(index=0;index<-i;index++){
            printf("index %d\n",index);
            value += inputData[0] +inputData[i];
            value+=(2*inputData[index]);
        }
        value *=h;
        fprintf(outputFile,"%lf ",value);
        value =0;
    }
    fclose(inputFile);
    fclose(outputFile);
    free(inputData);
    return 0;}

任何想法怎么做?

更新

while((i = fread(inputData,sizeof(double),N,inputFile))==N){
    value = (inputData[0] + inputData[N])/2.0;
    for(index=1;index<N;index++){
        value+=inputData[index];
    }
    value *=h;
    fprintf(outputFile,"%lf ",value);
    printf(" value %lf\n",value);
    value =0;

}

我得到199.000作为每个细分的结果。

2 个答案:

答案 0 :(得分:2)

为什么你没有从简单的事情开始。假设您有以下数据{1,2,3,4,5,6,7,8,9,10}并假设h = 1。这很简单,

#include <stdio.h>

#define SIZE 10

int main()
{
    double a[SIZE] = {1,2,3,4,5,6,7,8,9,10}, sum = 0.0, trapz;
    int h = 1;
    int i = 0;

    for ( i; i < SIZE; ++i){
        if ( i == 0 || i == SIZE-1 ) // for the first and last elements
            sum += a[i]/2;
        else
            sum += a[i]; // the rest of data
    }   
    trapz = sum*h; // the result

    printf("Result: %f \n", trapz);
    return 0;
}

这是结果

Result: 49.500000

使用Matlab仔细检查您的工作:

Y = [1 2 3 4 5 6 7 8 9 10];
Q = trapz(Y)

Q =

   49.5000

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$

编辑:对于评论中的问题: 这是matlab代码:

X = 0:pi/100:pi; % --> h = pi/100
Y = sin(X); % get values as many as the size of X
Q = trapz(X,Y);
Q =
    1.9998

现在要在C中实现相同的方案,请执行以下操作

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

#define SIZE 101

#define PI 3.14159265358

int main()
{
    double X[SIZE], Y[SIZE], incr = 0.0, h = PI/100.0, sum = 0.0, trapz;
    int i = 0, k = 0, j = 0;

    // Generate samples
    for ( i; i < SIZE; ++i)
    {
        X[i] = incr;
        incr += h;
    }

    // Generate the function Y = sin(X)
    for ( k; k < SIZE; ++k)
    {
        Y[k] = sin(X[k]);
    }

    // Compute the integral of sin(X) using Trapezoidal numerical integration method
    for ( j; j < SIZE; ++j){
        if ( j == 0 || j == SIZE-1 ) // for the first and last elements
            sum += Y[j]/2;
        else
            sum += Y[j]; // the rest of data
    }   
    trapz = sum * h; // compute the integral

    printf("Result: %f \n", trapz);

    return 0;
}

结果是

Result: 1.999836

答案 1 :(得分:1)

首先,你的等式是正确的,所以这是一个良好的开端。但是,您的问题中有许多变量声明没有提供,因此我们不得不猜测。

首先,让我们从数学开始。对于从0到100等于200的积分,每个值等于2.0意味着h = 1,但您的代码似乎使用22050/2的值,这可能不是您想要的。

循环中的代码应如下所示:

double value = (inputData[0] + inputData[N])/2.0;
for(index = 1; index < N; ++index){
    value += inputData[index];
}
value *= h;

这将提供从0N的积分。如果您希望在两个任意值之间进行计算,则必须适当地修改代码:

int a = 100;  // lower limit
int b = 200;  // upper limit 

double value = (inputData[a] + inputData[b])/2.0;
for(index = a+1; index < b; ++index){
    value += inputData[index];
}
value *= h;

作为一个完整的使用示例,这是一个计算sin(x)x=pi/4x=pi/2的积分的程序:

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

#define M_PI        3.14159265358979323846

int main()
{
    int a = 45;   // 45 degrees = pi/4 radians
    int b = 90;   // 90 degrees = pi/2 radians
    double h = M_PI/180;   // how far apart are samples?
    double *inputData = malloc(360*sizeof(double));
    if (inputData == NULL) {
        printf("Error: ran out of memory!\n");
        exit(1);
    }
    for (int i=0; i<360; ++i)
        inputData[i] = sin(i*h);

    double value = (inputData[a] + inputData[b])/2.0;
    for (int index = a+1; index < b; ++index)
        value += inputData[index];
    value *= h;
    printf("integral from %d to %d = %f\n", a, b, value);
    double expected = 1.0/sqrt(2);
    printf("(expected value = %f, error = %f)\n", expected, expected-value);
    free(inputData);
}

我的机器上此程序的输出:

integral from 45 to 90 = 0.707089
(expected value = 0.707107, error = 0.000018)