Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Странная проблема с выводом double на консоль.

15K
03 марта 2010 года
DragonHT
38 / / 02.08.2007
Здравствуйте. Вопрос действительно может показаться глупым.
При написании учебной программы для вычисления функции с помощью QUANC8 и SPLINE SEVAL столкнулся с небольшой проблемой функция seval вместо решения функции в окрестности заданной точки выдаёт непонятные значения:
Цитата:
-1.#IND


Вроде проверил всё что может грешить не могу понять в чём дело, все подозрения падают на функцию seval.
Все кого спрашивал, говорят что проблема в индексации памяти, вопрос как решить эту проблему. Помогите, может быть кто-то знает как решить эту проблему или в чём ошибка? Очень на вас надеюсь
Прилагаю: [INDENT]Свой Код(Main.cpp):

Код:
#include <iostream>
#include <math.h>
#include "quanc8.h"
#include "splines.h"
using namespace std;
double x[100], f[100], xk[100], h, sx, lx, ux, A, B, FLAG, ERREST, RELERR, ABSERR, b[100],c[100],d[100], sR[100];
double xSpline, ss;
int k[100], NOFUN, i, n;
double FUN ( double t)
{
    return exp(x*t)*sin(t);
}

void main()
{

    cout<<"Insert lower limit of 'x'."<<endl; // начало промежутка для х, узлов
    cin>>lx;
    sx=lx;
    cout<<"Insert upper limit of 'x'."<<endl; // конец промежутка для х, узлов
    cin>>ux;
    cout<<"Insert step of 'x'."<<endl; // шаг увеличения значения узлов
    cin>>h;
    cout<<"Insert lower limit of integration."<<endl; // нижний предел интегрирования для QUANC8
    cin>>A;
    cout<<"Insert upper limit of integration."<<endl; // верхний предел интегрирования для QUANC8
    cin>>B;
    cout<<"Insert absolut error."<<endl; // Абсолютная погрешность
    cin>>ABSERR;
    cout<<"Insert relative error."<<endl; // Относительная погрешность
    cin>>RELERR;
    cout<<"Value of 'X' | Value of F"<<endl;
    //Вычисление и вывод значений функции в заданных узлах
    for ( i=0; sx<=ux; i++ )
    {
        x=sx;
        sx+=h;
        quanc8( FUN, A, B, ABSERR, RELERR, &f, &ERREST, &NOFUN, &FLAG);
        cout<<x<<"\t|\t"<<f<<endl;

    }
    cout<<"Insert step of 'x' for spline nodes."<<endl; // Шаг для узлов в которых необходимо вычислить сплайн-функцию
    cin>>ss;
    n=i;
    i=0;
    spline(n,x,f,b,c,d);
    xSpline=0.1;
    cout<<"Value of 'xSpline' | Value of function in area of 'xSpline'"<<endl;
    // Вывод значений полученных в результате решения сплайна
    for ( i=0; i<n; i++ )
    {
        sR=seval(n, &xSpline, x, f, b, c, d);
        cout<<xSpline<<"\t|\t"<<sR<<endl;
        xSpline+=ss;
       
    }
}

Программа QUANC8:[INDENT]quanc8.h:
 
Код:
// quanc8.h

#ifndef _QUANC8
#define _QUANC8

void quanc8(double (*FUN)(double), double A, double B, double ABSERR,
            double RELERR, double *RESULT, double *ERREST, int *NOFUN, double *FLAG);

#endif

quanc8.cpp
Код:
// quanc8.cpp
#include "quanc8.h"
#include <math.h>

void quanc8(double (*FUN)(double), double A, double B, double ABSERR,
            double RELERR, double *RESULT, double *ERREST, int *NOFUN, double *FLAG)
            /*
            Integrale di FUN(X) da A a B

            Routine automatica di tipo adattivo basata
            sulle formule di Newton-Cotes ad 8 intervalli.
            Input
            FUN     nome della funzione integranda  che viene fornita nella
            function FUN(X) di tipo double con argomento double.
            A       limite inferiore di integrazione.
            B       limite superiore di integrazione.
            RELERR  errore relativo.
            ABSERR  errore assoluto.
            Output
            RESULT  una approssimazione dell'integrale che dovrebbe soddisfare
            la precisione data dal meno rigoroso dei due errori
            ERREST  stima della grandezza dell'errore commesso
            NOFUN   numero di volte in cui la funzione e' stata calcolata
            FLAG    indicatore di attendibilita'; se FLAG e' zero si e'
            ottenuta la precisione richiesta.
            se FLAG e' xxx.yyy allora xxx= il numero di intervalli in cui non e'
            stata raggiunta la precisione richiesta, mentre 0.yyy ci da' una
            indicazione sul punto nell'intorno del quale non si e' raggiunta la
            precisione richiesta.
            */
{
    double QRIGHT[32],F[17],X[17],FSAVE[9][31],XSAVE[9][31];
    int LEVMIN,LEVMAX,LEVOUT,NOMAX,NOFIN,LEV,NIM,J,I;
    double W0,W1,W2,W3,W4,COR11,AREA,X0,F0,STONE,STEP;
    double QLEFT,QNOW,QDIFF,QPREV,TOLERR,ESTERR;

    /*     ***  PASSO 1 *** INIZIALIZZAZIONE GENERALE COSTANTI */

    LEVMIN=1;
    LEVMAX=30;
    LEVOUT=6;
    NOMAX=5000;
    NOFIN=NOMAX-(8*(LEVMAX-LEVOUT+pow(2,(double)(LEVOUT+1))));

    /*     ISTRUZIONI RIGUARDO AL CASO IN CUI NOFUN RAGGIUNGE IL VALORE NOFIN */

    W0=3956.0/14175.0;
    W1=23552.0/14175.0;
    W2=-3712.0/14175.0;
    W3=41984.0/14175.0;
    W4=-18160.0/14175.0;

    /*     INIZIALIZZO LE SOMME CORRENTI A ZERO */

    *FLAG=0.0;
    *RESULT=0.0;
    COR11=0.0;
    *ERREST=0.0;
    AREA=0.0;
    *NOFUN=0;
    if(A == B)
        return;

    /*     ***  PASSO 2 ***  INIZIALIZZAZIONE RELATIVA AL PRIMO INTERVALLO */

    LEV=0;
    NIM=1;
    X0=A;
    X[16]=B;
    QPREV=0.0;
    F0=FUN(X0);
    STONE=(B-A)/16.0;
    X[8]=(X0+X[16])/2.0;
    X[4]=(X0+X[8])/2.0;
    X[12]=(X[8]+X[16])/2.0;
    X[2]=(X0+X[4])/2.0;
    X[6]=(X[4]+X[8])/2.0;
    X[10]=(X[8]+X[12])/2.0;
    X[14]=(X[12]+X[16])/2.0;
    for (J=2; J<=16; J=J+2){
        F[J]=FUN(X[J]);
    }
    *NOFUN=9;

    /*     ***  PASSO 3 ***  PARTE CENTRALE RIGUARDANTE I CALCOLI
    QUESTI CALCOLI IMPIEGANO I VALORI DI QPREV,X0,X2,X4,...X16,F0,F2,...F16.
    SI DETERMINANO I VALORI  X1,X3,...X15,F1,F3,...F15,QLEFT,QRIGTH,QNOW,
    QDIFF,AREA. */

trenta:
    X[1]=(X0+X[2])/2.0;
    F[1]=FUN(X[1]);
    for (J=3; J<=15; J=J+2){
        X[J]=(X[J-1]+X[J+1])/2.0;
        F[J]=FUN(X[J]);
    }
    *NOFUN=*NOFUN+8;
    STEP=(X[16]-X0)/16.0;
    QLEFT=(W0*(F0+F[8])+W1*(F[1]+F[7])+W2*(F[2]+F[6])+W3*(F[3]+F[5])
        +W4*F[4])*STEP;
    QRIGHT[LEV+1]=(W0*(F[8]+F[16])+W1*(F[9]+F[15])+W2*(F[10]+F[14])
        +W3*(F[11]+F[13])+W4*F[12])*STEP;
    QNOW=QLEFT+QRIGHT[LEV+1];
    QDIFF=QNOW-QPREV;
    AREA=AREA+QDIFF;

    /*     *** PASSO 4 ***  TEST SULLA CONVERGENZA */

    ESTERR=fabs(QDIFF)/1023.0;
    if (ABSERR > (RELERR*fabs(AREA))*(STEP/STONE))
        TOLERR=ABSERR;
    else
        TOLERR=(RELERR*fabs(AREA))*(STEP/STONE);
    if (LEV < LEVMIN)
        goto cinquanta;
    if (LEV >= LEVMAX)
        goto sessantadue;
    if (*NOFUN > NOFIN)
        goto sessanta;
    if (ESTERR <= TOLERR)
        goto settanta;

    /*     *** PASSO 5 *** CASO DELLA NON CONVERGENZA */

cinquanta:
    NIM=2*NIM;
    LEV=LEV+1;

    /*  SI MEMORIZZA CIO' CHE PUO' SERVIRE PIU' AVANTI  */

    for (I=1; I<=8; I++) {
        FSAVE[LEV]=F[I+8];
        XSAVE[LEV]=X[I+8];
    }

    /*  SI ELABORA CIO' CHE SERVE ORA */

    QPREV=QLEFT;
    for (I=1; I<=8; I++) {
        J=-I;
        F[2*J+18]=F[J+9];
        X[2*J+18]=X[J+9];
    }
    goto trenta;

    /*     *** PASSO 6 ***  ISTRUZIONI RELATIVE AL CASO IN CUI  CI SONO DELLE
    DIFFICOLTA'.
    CIOE'  QUANDO IL NUMERO DEI VALORI DELLA FUNZIONE USATI PER
    DETERMINARE  RESULT SUPERA I LIMITI POSTI */

sessanta:
    NOFIN=2*NOFIN;
    LEVMAX=LEVOUT;
    *FLAG=*FLAG+((B-X0)/(B-A));
    goto settanta;

    /*    IL LIVELLO CORRENTE E' LEVMAX */

sessantadue:
    *FLAG=*FLAG+1.0;

    /*     *** PASSO 7 ***  CASO DELLA CONVERGENZA
    SOMMO I CONTRIBUTI TROVATI ALLE SOMME CORRENTI */

settanta:
    *RESULT=*RESULT+QNOW;
    *ERREST=*ERREST+ESTERR;
    COR11=COR11+QDIFF/1023.0;

    /*     DETERMINO IL PROSSIMO INTERVALLO */

    while (NIM%2 != 0) {
        NIM=NIM/2;
        LEV=LEV-1;
    }
    NIM=NIM+1;
    if (LEV <= 0)
        goto ottanta;

    /*     ELABORO GLI ELEMENTI  RELATIVI AL PROSSIMO INTERVALLO */

    QPREV=QRIGHT[LEV];
    X0=X[16];
    F0=F[16];
    for (I=1; I<=8; I++) {
        F[2*I]=FSAVE[LEV];
        X[2*I]=XSAVE[LEV];
    }
    goto trenta;

    /*     ***  PASSO 8 ***  DETERMINO GLI ULTIMI RISULTATI */

ottanta:
    *RESULT=*RESULT+COR11;
    if (*ERREST == 0.0)
        return;
    while (fabs(*RESULT)+(*ERREST) == fabs(*RESULT))
        *ERREST=2.0*(*ERREST);
    return;
}

[/INDENT]Код программ SPLINE, SEVAL:[INDENT]splines.h
 
Код:
#ifndef _SPLINES
 #define _SPLINES

    void spline(int n,double * x,double * y,double * b,double * c,double * d);
    double seval(int n, double * u,
         double * x,double * y,double * b,double * c,
         double * d);

#endif

splines.cpp
Код:
#include "splines.h"
#include <math.h>

void spline(int n,double * x,double * y,double * b,double * c,double * d)
{
     int i,ib,nm1;
     double t ;

    nm1=n-1;
     if (n < 2)  return;
     if (n < 3)  goto l20;
    d[1]=x[2]-x[1];
    c[2]=(y[2]-y[1])/d[1];
     for (i=2 ;i<=nm1;i++)
     {
      d=x[i+1]-x;
      b=2*(d[i-1]+d);
      c[i+1]=(y[i+1]-y)/d;
      c=c[i+1]-c;
     }
    b[1]=-d[1];
    b[n]=-d[n-1];
    c[1]=0;
    c[n]=0;
     if (n == 3) goto l10;
    c[1]=c[3]/(x[4]-x[2])-c[2]/(x[3]-x[1]);
    c[n]=c[n-1]/(x[n]-x[n-2])-c[n-2]/(x[n-1]-x[n-3]);
    c[1]=c[1]*sqrt(d[1])/(x[4]-x[1]);
    c[n]=-c[n]*sqrt(d[n-1])/(x[n]-x[n-3]);

l10:    for (i=2;i<=n;i++)
       {
        t=d[i-1]/b[i-1];
        b=b-t*d[i-1];
        c=c-t*c[i-1];
       }
    c[n]=c[n]/b[n];
      for (ib=1;ib<=nm1;ib++)
      {
       i=n-ib;
       c=(c-d*c[i+1])/b;
      }
    b[n]=(y[n]-y[nm1])/d[nm1]+d[nm1]*(c[nm1]+2*c[n]);
       for (i=1;i<=nm1;i++)
       {
        b=(y[i+1]-y)/d-d*(c[i+1]+2*c);
        d=(c[i+1]-c)/d;
        c=3*c;
       }
     c[n]=3*c[n];
     d[n]=d[n-1];
     return;
l20:  b[1]=(y[2]-y[1])/(x[2]-x[1]);
     c[1]=0;
     d[1]=0;
     b[2]=b[1];
     c[2]=0;
     d[2]=0;

l30:
  return;
  }

  double seval(int n, double * u,
         double * x,double * y,double * b,double * c,
         double * d)
 {
   int i,j,k;
   double dx;
   i=1;
    if (i >= n) i=1;
     if (*u < x) goto l10;
      if (*u <= x[i+1]) goto l30;

l10: i=1;
    j=n+1;


l20: k=(i+j) / 2;
     if (*u < x[k]) j=k;
      if (*u >= x[k]) i=k;
       if (j > (i+1)) goto l20;

l30: dx=*u-x;
    return y+dx*(b+dx*(c+dx*d));
 }
[/INDENT][/INDENT]
Среда разработки: Visual Studio 2008
Операционная система: Windows 7, а также проверенно на Windows XP
9.0K
04 марта 2010 года
grag63
71 / / 23.01.2006
В опреациях деления, проверь чтобы делитель не являля 0.0.
Думаю поможет.
15K
04 марта 2010 года
DragonHT
38 / / 02.08.2007
Деление на ноль отметается...
Эти реализации кванка/севала/сплайна проверены в течении нескольких лет. Этот код выдавал преподаватель. Файлы несколько раз перезаливал (вдруг я накасячил когда код листал) не помогает.
1.9K
04 марта 2010 года
Rad87
123 / / 14.12.2005
Разбирайся в арифметике... где то получается минус бесконечность.
12K
06 марта 2010 года
Ghox
297 / / 26.07.2009
DragonHT, а программная функция
 
Код:
double FUN ( double t)
{
    return exp(x*t)*sin(t);
}

представляет ту самую математическую функцию, решение для которой вы хотите найти? Если да, то как-то странным выглядит использование в ней, для вычисления результата, глобального массива x, и глобальной переменной-индекса i. Как мне думается, в подобных случаях возвращаемый программной функцией результат должен целиком и полностью зависеть только от передаваемых в функцию аргументов (в данном случае - от double t). Так что, может быть, надо умножение на x удалить, оставить только exp(t)*sin(t).

И еще учтите, что здесь у вас используется экспонента от x (функция exp из библиотеки math), которая очень быстро возрастает при увеличении аргумента. Возможно из-за этого у вас и возникает то о чем говорят предыдущие авторы (то что где-то получается бесконечность).

Посмотрел также на код функции seval, на которую вы грешите. Прежде всего бросается в глаза очевидная нелепость:
 
Код:
i=1;
    if (i >= n) i=1;

Вторая операция не имеет здесь абсолютно никакого смысла. Почему - предлагаю вам подумать самостоятельно.

Есть также замечания по структурированию программного кода в следующем фрагменте:
Код:
if (*u < x) goto l10;
      if (*u <= x[i+1]) goto l30;

l10: i=1;
    j=n+1;


l20: k=(i+j) / 2;
     if (*u < x[k]) j=k;
      if (*u >= x[k]) i=k;
       if (j > (i+1)) goto l20;

l30: dx=*u-x;
    return y+dx*(b+dx*(c+dx*d));

Во-первых, использование операторов goto считается дурным тоном, здесь вполне можно обойтись без goto.

Во-вторых, в блоке обозначенном меткой 120, есть два условия if (*u < x[k]) и (*u >= x[k]). Так вот второе можно не писать, а написать else после первого, т.к. если выполняется первое, то не выполняется второе, и наоборот.

Вот полный эквивалент этого фрагмента кода, с устранением этих замечаний:
Код:
if(*u < x || *u > x[i+1])
    {
        i = 1;
        j = n + 1;
        do
        {
            k = (i + j) / 2;
            if (*u < x[k])
                j = k;
            else
                i = k;
        }
        while(j > (i + 1));
    }
    dx = *u - x;
    return y + dx * (b + dx * (c + dx * d));

Думаю, не будете возражать, что если так переписать, то логика работы программы становится гораздо более понятней чем в том варианте, что у вас? :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог