【问题标题】:Code works on MinGW but not on my uni's computer (Language C)代码适用于 MinGW,但不适用于我的 uni 计算机(语言 C)
【发布时间】:2013-06-19 12:18:27
【问题描述】:

我必须编写一个程序,使用辛普森法和梯形法计算函数的积分。它在我使用 MinGW 的计算机上运行良好,但是当我尝试在我的 uni 计算机上编译它时,我得到:

It = 0 //should be 0.954499
*pn = 0 //should be 18
Is = 0 //should be 0.954500
*pn = 0 //should be 6

这是我想出来的(对不起,变量和cmets是葡萄牙语,我回家后会修复它):

integral.h:

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

#define eps 1.e-6
#define kmax 20

double trapezio(double (*f)(double x), double a, double b, int *n);
double simpson(double (*f)(double x), double a, double b, int *n);

integral.c:

#include "integral.h"
#define xmin -2
#define xmax 2

double f(double x);

int main(){
    double It,Is;
    int n = 0;
    int *pn = NULL;

    pn = &n;
    It = trapezio(f,xmin,xmax,pn)/sqrt(2*M_PI);
    printf("Pelo metodo dos trapezios a integral vale aproximadamente %lf\n", It);
    printf("O numero de iteracoes usadas foi %d\n\n",*pn);

    *pn = 0;
    Is = simpson(f,xmin,xmax,pn)/sqrt(2*M_PI);
    printf("Pelo metodo de simpson a integral vale aproximadamente %lf\n", Is);
    printf("O numero de iteracoes usadas foi %d\n",*pn);

    return 0;
}

double f(double x){
    return exp(-0.5*x*x); // Funcao que sera integrada
}

trapezio.c:

#include "integral.h"

double trapezio(double (*f)(double x), double a, double b, int *n){
    double To, Tk;
    double soma;
    int i, k = 1;
    Tk = 0.5*(f(a) - f(b))*(b - a);

    while (fabs((Tk-To)/To) > eps && k < kmax){
        soma = 0; // Resetando variavel soma
        To = Tk; // To e' T(k - 1), caso o loop se repita o ultimo Tk vira To
        for (i = 1 ; i <= (pow(2,k)-1) ; i += 2) soma += f(a + i*(b - a)/pow(2.,k));
        Tk = 0.5*To + soma*(b - a)/pow(2.,k);
        k++;
        *n += 1;
    }

    return Tk;
}

辛普森.c:

#include "integral.h"

double simpson(double (*f)(double x), double a, double b, int *n){
    double So, Sk = 0;
    double somaimp, somapar;
    int i, k = 1;

    while (fabs((Sk-So)/So) > eps && k < kmax){
        somaimp = 0;
        somapar = 0;
        So = Sk; // So e' S(k - 1)
        for (i = 1; i <= (pow(2,k)-1); i += 2) somaimp += f(a + i*(b - a)/pow(2.,k));
        for (i = 2; i <= (pow(2,k)-2); i += 2) somapar += f(a + i*(b - a)/pow(2.,k));
        Sk = (b - a)*(f(a) + 4*somaimp + 2*somapar + f(b))/(3*pow(2.,k));
        k++;
        *n += 1;
    }

    return Sk;
}

编辑:我忘了说如果我把指针拿出来,梯形图可以工作,但 simpson 仍然返回 0。

【问题讨论】:

  • 你uni的电脑上的操作系统和编译器是什么?

标签: c pointers gcc mingw


【解决方案1】:

trapezio() 中,在while 循环中使用之前,您永远不会初始化To

double To, Tk;
/* ... no assignment to To ... */
while (fabs((Tk-To)/To) > eps && k < kmax){

这意味着它将以未定义的方式运行,并且可能根本不会进入循环。

【讨论】:

  • 我以为既然我在循环开始后立即定义了To,就没有问题,但是我忘记了循环条件取决于To。谢谢。 :)
  • 最近的 MSVC 编译器默认会发出警告(至少从 VS 2005 开始)。有趣的是,即使使用-Wuninitialized -Wmaybe-uninitialized,我也无法让 gcc 对这种特殊情况发出警告。
  • 为什么我的代码可以在 MinGW 上运行呢?它是否将我的 while 循环视为 do/while 循环?这很奇怪。
  • 啊哈 - 要让 gcc 对此发出警告,除了 -Wuninitialized 之外,您还必须至少启用一些优化 (-O1)。这实际上在 gcc 文档中提到,但这肯定不是我所期望的。
  • @NatashaRocha:未定义行为的本质是它看起来也可以工作。在您的“良好”运行中,To 变量碰巧具有一些合理的价值。
猜你喜欢
  • 2022-09-28
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 2017-05-03
相关资源
最近更新 更多