Obliczanie pola metodą Monte Carlo

1

Witam,
Mam do napisania program, który obliczy pole między osią O(x), a funkcją sin(x). Pole ma zostać obliczone metodą Monte Carlo i dodatkowo być ograniczone w przedziale [a,b].
Jako, że jestem początkującym, proszę o jakąkolwiek podpowiedź, bądź nakierowanie gdzie mógłbym dowiedzieć się jak to zrobić.

Z góry dziękuję.

0

Po długich poszukiwaniach nadal nie bardzo wiem jak to zrobić... . Może mógłby ktoś podać jak np. wpleść tego sin(x) i ograniczyć go od 0 do 1.
Dopiero zaczynam każda rada jest dla mnie na wagę złota. ;p

1
  • losujesz liczbę 'x' z przedziału [a,b]
  • losujesz liczbę 'y' z przedziału [-1,1]
  • sprawdzasz, czy punkt (x,y) leży między osią X a sinusoidą sin(X)
  • i tak w kółko wiele razy zliczając ilość trafień

Wynikiem jest

*pole * ilosc_trafien / ilosc_prob*

gdzie pole to pole powierzchni obszaru z jakiego losujemy punkty czyli 2(b-a)*

Dodam jeszcze, że metoda monte-carlo w tym przypadku jest bez sensu. Aby jej użyć musimy użyć funkcji sinus. A skoro można użyć funkcji sinus to można to pole wyliczyć analitycznie (całka z sinusa to kosinus).

0

Ok, napisałem coś takiego. Ale program nie chce działać i nie bardzo wiem jak uwzględnić fakt, że sinus ma być nad osią x. Jakieś rady?

double sinus(double x)
{
    return sin(x);
}

int main(int argc, char *argv[])
{
    int n;
    double a,b,wynik,y,llos,Pole;
    int i;

    printf("Podaj poczatek przedzialu= \n");
    scanf("%f", &a);
    printf("Podaj koniec przedzialu= \n");
    scanf("%f", &b);
    printf("Podaj liczbe punktow losowych= \n");
    scanf("%d", &n);

    srand((unsigned)time(NULL));
    y = b - a;

    for (i=1; i<=n; i++)
    {
        llos += sinus(a+((double)rand()/(double)(RAND_MAX+1)*y));
    }

    Pole = (y * llos)/ n;

    printf("Pole wynosi= %f", &Pole);
    system("PAUSE");
    return 0;
}
0

sinus ma być nad osią x
Wcale nie.

Jakieś rady?
A jest nad B wtedy, i tylko wtedy, gdy y(A) > y(B).

0

Hej mam problem z monte carlo mam obliczyć pole z funkcji:
Górne ograniczenie: f(x) = -x^2 + 5
Dolne ograniczenie: g(x) = x^2 - 5
Mogę poprsoić o jakieś wskazówki widziałem na algorytmy.org coś takiego lecz nie bardzo wiem jak uwzlędnić dolne ograniczenie
http://www.algorytm.org/procedury-numeryczne/calkowanie-numeryczne-metoda-monte-carlo-ii.html

0

Wyznaczasz punkty przecięcia parabol(-sqrt(5), sqrt(5)). Losujesz punkty (x,y) z prostokąta [-sqrt(5),sqrt(5)] x [-5,5], dla każdego wylosowanego punktu sprawdzasz czy
y <= -x2 + 5 oraz y >= x2 - 5.

0

Dalej nie rozumiem możecie zerknąć na to ?

namespace metoda_monte_carlo_cs
{
    /// <summary>
    /// Metoda Monte-Carlo.
    /// </summary>
    class Metoda_Monte_Carlo
    {

        private static Random rand = new Random();

        private static double randomPoint(double a, double b)
        {
            return -Math.Sqrt(a) + rand.NextDouble() * (Math.Sqrt(b) + -Math.Sqrt(a));
        }

        private static double calculate(double xp, double xk, double yp, double yk, int n)
        {
            double calka;
            int pointsIn;

            pointsIn = 0;

            for (int i = 0; i < n; i++)
            {
                pointsIn += funcIn(randomPoint(xp, xk), randomPoint(yp, yk));
            }

            calka = (pointsIn / (n * 1.0)) * ((xk - xp) * (yk - yp));
            return calka;
        }

        //funkcja dla ktorej obliczamy calke
        private static double funcUpper(double x)
        {
            return x * x - 5;
        }

        private static double funcUnder(double x)
        {
            return -(x * x) + 5;
        }

        //1 jeżeli punkt leży nad osią OY i jednocześnie pod wykresem funkcji całkowanej
        //-1 jeżeli punkt leży pod osią OY i jednocześnie nad wykresem funkcji całkowanej
        //0 w przeciwnym razie
        private static int funcIn(double x, double y)
        {
            if ((y > 0) && (y <= funcUnder(x)))
                return 1;
            else if ((y > 0) && (y >= funcUpper(x)))
                return -1;
            return 0;
        }

        static void Main(string[] args)
        {
            double xp, xk, yp, yk;
            int n;

            Console.WriteLine("Podaj poczatek przedzialu calkowania");
            xp = double.Parse(Console.ReadLine());

            Console.WriteLine("Podaj koniec przedzialu calkowania");
            xk = double.Parse(Console.ReadLine());

            Console.WriteLine("Podaj dokladnosc calkowania (w setkach punktow)");
            n = int.Parse(Console.ReadLine());
            n *= 100;

            yp = Math.Ceiling(Math.Max(funcUnder(xp), funcUnder(xk)));
            yk = Math.Ceiling(Math.Max(funcUpper(xp), funcUpper(xk)));

            Console.WriteLine("Wartosc clki wynosi w przyblizeniu " + calculate(xp, xk, yp, yk, n));
            Console.ReadKey();
        }
    }
}
0

Zła funkcja funcIn (nigdy nie powinna zwracac -1)
private static int funcIn(double x, double y)
{
if ((y >= funcUpper(x)) && (y <= funcUnder(x)))
return 1;
return 0;
}

0

Źle losujesz punkty, x musi być z przedziału [a,b], y powinno być z przedziału [-5,5]
private static double randomPoint(double a, double b)
{
return a + rand.NextDouble() * (b - a);
}
...
yp = -5;
yk = 5;

0
bogdans napisał(a):

Zła funkcja funcIn (nigdy nie powinna zwracac -1)
private static int funcIn(double x, double y)
{
if ((y >= funcUpper(x)) && (y <= funcUnder(x)))
return 1;
return 0;
}



Z wykresu wynika że y może być pod lub nad obiema funkcjami i być w polu.
Czyli coś bardziej jak:

```java
        private static int funcIn(double x, double y)
        {
            if ((y >= funcUpper(x)) && (y <= funcUnder(x)))
                return 1;
            if ((y <= funcUpper(x)) && (y >= funcUnder(x)))
                return 1;
            return 0;
        }

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