【问题标题】:Calculate Derivative, given data file计算导数,给定数据文件
【发布时间】:2014-04-07 16:03:43
【问题描述】:

所以,这是我在课堂上遇到的一个 C 编程问题。要解决这个问题,您需要知道导数的基本形式。以下是说明。

这就是我想要做的...... 给定 txt 文件,我会读入一个值,然后在刚刚读取的值之前读入该值。我尝试使用两个for 循环,但这似乎没有按预期工作。我不能在这个程序中使用数组——(在我看来,这会使这个问题变得微不足道)。

目前有四个for 循环。第一对用于计算 f'(x),第二对用于计算 f''(x)。

这是我的代码。评论太多了,先见谅。

// Lab7_Prob2.cpp : Computes derivatives of functions... FML
// nxt3

#include "stdafx.h"
#include <stdio.h>
#define SUCCESS printf("File operations were successful!\n");

/*function that calculates derivative*/
double derive(double x_i, double fX_i, double x_i2, double fX_i2) {

/*x_i, f(x_i); x_i2 = (x_i + 1), fX_i2 = f(x_i + 1)*/
double fprime = (fX_i2 - fX_i) / (x_i2 - x_i); //derivative of x, f'(x)

return fprime; //returns f'(x)
}

int main() {

double x, fX, x2, fX2; //init variable for x and f(x); also, (x_i+1) and (f(x_i+1))
double fP, f2P, xp2, fXp2; //init variables for f'(x), f''(x), f'(x_i) and f'(x_i+1)
int i = 1, j = 1; //indices for both MAIN loops, i = MainLoop1, j = MainLoop2
int ss = -99; //sentinal signal for secondderiv.txt
FILE *dt; //ptr for deriv_testdata.txt
FILE *fd; //ptr for firstderiv.txt
FILE *sd; //ptr for secondderiv.txt

dt = fopen("C:/Users/ng00947/Downloads/DataFiles/deriv_testdata.txt", "r"); //opens deriv_testdata.txt
fd = fopen("C:/Users/ng00947/Downloads/DataFiles/firstderiv.txt", "w"); //creats firstderiv.txt
sd = fopen("C:/Users/ng00947/Downloads/DataFiles/secondderiv.txt", "w"); //creats secondderiv.txt

int mNumDataPts; //number of records from deriv_testdata.txt
fscanf(dt, "%i", &mNumDataPts); //grabs number of records from file
fprintf(fd, "%i\n", (mNumDataPts - 1)); //prints number of records to firstderiv.txt

//209 data points for f'(x)
//208 data points for f''(x)

/*loop scans in a uses derive function to calculate f'(x)*/
for (i; i <= (mNumDataPts - 1); i++) { //MainLoop1
    fscanf(dt, "%lf %lf", &x, &fX); //grabs values in each row for x and f(x)

    /*loop grabs values one ahead of x and f(x); this is for (x_i+1) and f(x_i+1)*/
    for (int k = i; k <= (i + 1); k++) { //SubLoop1
        fscanf(dt, "%lf %lf", &x2, &fX2);
        break; //leaves this loop to continue with main loop
    }

    fP = derive(x, fX, x2, fX2); //calculates derivative using function
    fprintf(fd, "%.2f \t %.2f\n", x, fP); //prints x and f'(x) to firstderiv.txt
}


/*loop scans in and uses derive function to calculate f''(x)*/
for (j; j <= (mNumDataPts - 2); j++) { //MainLoop2
    fscanf(fd, "%lf %lf", &x, &fP); //grabs values in each row for x and f'(x)

    /*loop grabs values one ahead of x and f'(x); this is for (x_i+1) and f'(x_i+1)*/
    for (int m = j; m <= (j + 1); m++) { //SubLoop2
        fscanf(dt, "%lf %lf", &xp2, &fXp2);
        break; //leaves this loop to continue with main loop
    }

    f2P = derive(x, fP, xp2, fXp2); //calculates second derivative using function
    fprintf(sd, "%.2f \t %.2f\n", x, f2P); //prints x and f''(x) to secondderiv.txt
}

fprintf(sd, "%i \t %i", ss, ss); //prints sentinal signal to end of secondderiv.txt

/*closes all files*/
fclose(dt);
fclose(fd);
fclose(sd);

SUCCESS; //prints message for sweet victory

return 0; //let's wrap this up
}

感谢所有帮助! (如果您可以在不提供代码的情况下帮助回答我的问题,则可以加分。)

这里是数据文件:

File given, deriv_testdata.txt

First Derivative, firstderiv.txt

Second derivative, secondderiv.txt

【问题讨论】:

  • 这可能无法解决问题,但强烈建议检查来自fscanf() 的返回值,这应该是2 是代码中的大多数(如果不是全部)情况。检查似乎是多余的,但健壮的代码使用它,这是一个很好的做法,即使在这里也是如此。

标签: c loops scanf derivative


【解决方案1】:

建议简化scan() 循环。

扫描第一对。在一个循环中(从索引 1 开始)扫描下一对,计算导数并打印。将第二对用作下一组的第一对。

static const char *format2double = "%lf%lf";  // space not needed in "%lf %lf"
if (fscanf(dt, format2double, &x, &fX) != 2) Handle_Error();

for (i = 1; i < mNumDataPts; i++) {
  if (fscanf(dt, format2double, &x2, &fX2) != 2) Handle_Error();
  fP = derive(x, fX, x2, fX2);
  fprintf(fd, "%.2f \t %.2f\n", x, fP); //prints x and f'(x) to firstderiv.txt
  x = x2;
  fX = fX2;
}

【讨论】:

  • yy2 是什么类型?在这个循环中没有使用yy2
  • @Nate 感谢您的询问 - 意思是 fxfx2
【解决方案2】:

计算一阶微分f'(x)。我认为您应该将您的子循环更改为

for (int k = i+1 ; k &lt;= (i + 1); k++) //change k=i+1

这将是找到双微分 f''(x) 的相同解决方案。将您的子循环更改为

for (int m = j+1; m &lt;= (j + 1); m++); //change m=j+1

*但是在这个循环中你写了continue; 就在for()loop 结束之前,我认为这是不合逻辑的,因为即使您将其删除,该循环将如何继续开始其下一次迭代。我想你可能想在那一行写break;(就像你在前面的子循环中找到 f'(x) 时写的那样)

【讨论】:

  • 这似乎没有任何作用。然而,由于某种原因,我的程序现在的设置方式(包括你写的),它跳过了 X 的值。这是数据文件。我正在读取 x 值(第一列)和 f(x) 值(第二列); x 的值永远不会改变,所以当我将它们打印到新文件时,第一列在所有三个文件中应该是相同的。事实并非如此。给定文件:deriv_testdata.txt 一阶导数:firstderiv.txt 二阶导数:secondderiv.txt
  • 在计算 f'(x) 后,您创建了一个文件 firstderiv.txt,要计算 f''(x),您正在读取以“写入模式”打开的同一个文件,您无法读取以写入模式打开的文件,因此您必须将其更改为fopen(" firstderiv.txt","r+");// change r to r+。在计算 f''(x) 之前,您还必须确保它们再次从文件中的起点读取,方法是添加这些 rewind(fd);rewind(dt);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 2018-12-17
相关资源
最近更新 更多