całka Monte Carlo

0

Cześć Koledzy, Koleżanki!
Dostalem takie zadanie.
Obliczanie całki oznaczonej wielomianu n-tego stopnia metodą Monte Carlo typu orzeł-reszka
Napisz program, który obliczy wartość całki oznaczonej w przedziale (k; l) dla dowolnego, wprowadzonego wielomianu n -tego stopnia.

Napisałem program, kompiluje się, ale niestety wydaje mi sie, że źle liczy;p
Mógłbym liczyć na jakieś podpowiedzi?

#include <iostream>
#include <cstdlib>
#include <time.h>
#include <cmath>
#include <cstdio>

using namespace std;

long double ZwrocWartoscFunkcji( int * wspolczynniki, int n, long double x );

int main()
{
    int ilosc, an, i, b, c, n;
    // Wczytujemy dane dotyczDce caEkowania, funkcje, przedziaEy.

    cout << "Podaj wspolczynnik przy n-tej potedze: " << endl;
    cin >> an;

    int * wspolczynniki = new int[ an ];

    for( i = 0; i <= an; i++ )
    {
        if( i == 0 ) cout << "Podaj wartosc wyrazu wolnego: " << endl; else
        cout << "Podaj wspolczynnik " << i << "stopnia wielomianu" << endl;
        cin >> wspolczynniki[ i ];
    }

    cout << "Podaj poczatek przedzialu calkowania: " << endl;
    cin >> b;

    cout << "Podaj koniec przedzialu calkowania: " << endl;
    cin >> c;

    // Wypisanie pobranej funkcji
    cout << "Wprowadzony wielomian to: " << endl;
    for( i = an; i >= 0; i-- )
    {
        if( i == 0 ) cout << wspolczynniki[ i ]; else
        cout << wspolczynniki[ i ] << "x^" << i;
        if( i > 0 )
        if( wspolczynniki[ i ] >= 0 ) cout << "+"; else cout << "-";
    }

    cout << endl << "Podaj dokladnosc wyznaczania max/min funkcji: ";
    cin >> n;

    // Max i Min lokalne funkcji w podanych przedziaEach wartoEci
    long double wartosc = 0, maximum = 0, minimum = 0, krok = 1.0 / n;

    // Wyliczamy wartosci funkcji w okreslonym przedziale, okreslamy minimum i maximum funkcji.
    for( double i = b; i <= c; i = i + krok )
    {
        wartosc = ZwrocWartoscFunkcji( wspolczynniki, an, i );

        if( wartosc > maximum ) maximum = wartosc;

        if( wartosc < minimum ) minimum = wartosc;

    }

    // Wyznaczamy wysokosc i szerokosc zakresu w ktorym bedziemy losowac.
    long double wysokosc, szerokosc;

    // Szerokosc to roznica przedzialu koncowego i poczatkowego.
    szerokosc =( long double )( c - b );

    // Wysokosc to roznica wartosci maxymalnej i minimalnej funkcji w przedziale.
    wysokosc = maximum - minimum;

    // Losowanie w punktow
    cout << "Podaj liczbe losowaE: " << endl << "Uwaga! Zakres od 1 do 2^32 - 1" << endl;
    cin >> ilosc;

    long double X = 0.0, Y = 0.0;
    int licznik = 0;

    for( i = 0; i < ilosc; i++ )
    {
        X =(( long double ) rand() /( RAND_MAX ) ) *( c - b ) + b;
        Y =(( long double ) rand() /( RAND_MAX ) ) *( wysokosc - szerokosc ) + szerokosc;

        wartosc = ZwrocWartoscFunkcji( wspolczynniki, an, i );

        if( Y > 0 && wartosc > 0 && Y <= wartosc ) licznik++;

        if( Y < 0 && wartosc < 0 && Y >= wartosc ) licznik--;

    }

    // Wartosc calki
    long double P;

    P =( szerokosc * wysokosc ) *( long double ) licznik /( long double ) ilosc;

    cout << "Punkty trafione: " << licznik << endl;
    cout << "WartoED calki: " << P << endl;

    int getchar();
    int getchar();
    return 0;
}

// Obliczanie wartoEci funkcji w x
long double ZwrocWartoscFunkcji( int * wspolczynniki, int n, long double x ) {
    long double funkcja = 0;

    for( int i = 0; i < n; i++ )
         funkcja +=(( long double ) wspolczynniki[ i ] ) *(( long double )pow( x,( double )( n - i - 1 ) ) );

    return funkcja;
}

pozdrawiam
Adam

0

Nie słyszałem, aby w metodzie Monte-Carlo istotne było max i minimum funkcji. Opracowania z których się sam uczyłem mówią, że mnoży się jedynie przedział(dokładnie różnice) jaki bierzemy pod uwagę w całce oznaczonej.
Parę wstępnych uwag:

  • Rozbij tą jedną funkcję na kilka mniejszych, np osobno wpisywanie całki oraz osobno liczenie.
  • Jeżeli interesuję Cię dłuższy kontakt z C++ to zachęcam do korzystania z biblioteki <random>.
  • Zamiast dynamicznie alokować tablice pomyśl nad vectorem <vector>

Czym jest to X oraz Y?
W metodzie Monte-Carlo nie sumuje się ilości punktów(tak rozumiem ten licznik cały), ale ich wartości w całce. Skonsultuj swój wynik z np WolframemAlpha.

0

Prawie wszystko nabadźgałeś w main, więc próba zrozumienia twojego kodu wymaga dużego wysiłku. A ile wysiłku musi wymagać znalezienie błędu?
Podziel to na małe logiczne funkcje, a problem sam się rozwiąże, jeśli nie to wtedy my łatwo znajdziemy ten błąd.

Np:

class Polynomial 
{
public:
    std::istream &read(std::istream &input);
    std::ostream &write(std::ostream &input) const;

    double calculate(double x) const;

private:
    std::vector<double> mA;
};

double monteCarloIntegrate(double x1, double x2, const Polynomial &f);
0

ok, to inaczej.

Mam juz wielomian, jak go teraz przekazac do funkcji w ktorej licze calke?

int main()
{
  double xp,xk,calka,dx,N;
  int i,an;

   cout << "Obliczanie calki oznaczonej\n"
          "    Metoda Monte Carlo\n"
          "---------------------------\n"
          "Podaj wspolczynnik przy n-tej potedze: " << endl;
    cin >> an;

 int * wspolczynniki = new int[ an ];

    for( i = 0; i <= an; i++ )
    {
        if( i == 0 ) cout << "Podaj wartosc wyrazu wolnego: " << endl; else
        cout << "Podaj wspolczynnik " << i << "stopnia wielomianu" << endl;
        cin >> wspolczynniki[ i ];
    }

  cout << setprecision(3)      // 3 cyfry po przecinku
       << fixed;                 // format stałoprzecinkowy


  cout << "Podaj poczatek przedzialu calkowania\n\n"
          "xp = ";
  cin >> xp;
  cout << "\nPodaj koniec przedzialu calkowania\n\n"
          "xk = ";
  cin >> xk;
  cout << endl;

   // Losowanie w punktow
    cout << "Podaj liczbe losowaE: " << endl << "Uwaga! Zakres od 1 do 2^32 - 1" << endl;
    cin >> N;

  // Wypisanie pobranej funkcji
    cout << "Wprowadzony wielomian to: " << endl;
    for( i = an; i >= 0; i-- )
    {
        if( i == 0 ) cout << wspolczynniki[ i ]<< endl; else
        cout << wspolczynniki[ i ] << "x^" << i;
        if( i > 0 )
        if( wspolczynniki[ i ] >= 0 ) cout << "+"; else cout << "-";
    }

Wyswietla sie i nie wiem jak go przekazac do funkcji

srand(time(NULL));
  calka  = 0;
  dx = xk - xp;
  for(i = 1; i <= N; i++)
    calka += funkcja(xp+((double)rand()/(double)(RAND_MAX+1)*dx));
  calka = dx * calka / N;
  cout << "Wartosc calki wynosi : " << setw(8) << s
       << endl << endl;
  system("pause");
  return 0;

1 użytkowników online, w tym zalogowanych: 0, gości: 1