Nowe posty

xx Problem ze sterownikami. (5)
2024-04-13, 21:25:16
xx Instalacja xfce4 (2)
2024-04-13, 16:20:17
xx Serie kompilacji bez instalacji dla “emerge” w Gentoo (2)
2024-04-08, 18:40:04
xx Plasma 6 w Neonie ssie trochę mniej ... (17)
2024-04-05, 10:03:46
xx Problem z Linux Lite po instalacji (3)
2024-04-03, 14:23:40
xx Jak właczyć num locka przy starcie systemu debian 12? (12)
2024-04-02, 17:43:54
xx Brak dźwieku w systemie. (5)
2024-04-02, 16:13:41
xx Dystrybucja pod HP Omen (7)
2024-03-29, 11:33:05
xx [Poradnik] Wyszukiwanie Sterowników (2)
2024-03-27, 21:08:23
xx Ile pingwinów? (1)
2024-03-27, 08:59:24

Autor Wątek: monte carlo  (Przeczytany 6302 razy)

Krzysiek1990

  • Gość
monte carlo
« dnia: 2010-02-05, 18:06:55 »
Witam!
Więc podczas nauki c++ natknąłem się na metodę monte carlo.

Mam taki kod:
using namespace std;

int main()
{
   int n;
    int nk = 0;
    double x,y;
    float s;
    cout << "Podaj liczbe losowanych pkt:" << endl;
    cin >> n;
    for(int i = 1; i <= n; i++)
       { x = ((double)rand() / (RAND_MAX)) * 2 - 1;
          y = ((double)rand() / (RAND_MAX))*2 - 1;
         if(sqrt(x*x + y*y) <= 1) { nk++; }
       }
   cout << "Liczba pkt. w kole wynosi: " << nk << endl;
   cout << "Liczba pkt. w kwadracie wynosi: " << n << endl;
   
   s = 4 * (double)nk / n;
   cout << "Liczba pi wynosi: " << s;

}
jak to właściwie działa?
 x = ((double)rand() / (RAND_MAX)) * 2 - 1;
Czy double to przedział między x, y? i czym jest RAND_MAX.

Z góry dziękuję za wyjaśnienie.
Pozdrawiam

Offline mateo86

  • Users
  • Guru
  • *****
  • Wiadomości: 647
    • Zobacz profil
monte carlo
« Odpowiedź #1 dnia: 2010-02-05, 18:17:36 »
Double jest rzutowaniem typu. Funkcja rand() zwraca wartość losowa typu integer (całkowita), a Tobie potrzebna jest liczba typu double (zmiennoprzecinkowa lub ułamkowa - jak kto woli). Float też by zdawało tu egzamin, tylko oczywiście byłaby mniejsza dokładność wyniku.

RAND_MAX jest stałą określającą zakres liczb wygenerowanych przez rand(). Sam ją definiujesz.

ZipoKing

  • Gość
monte carlo
« Odpowiedź #2 dnia: 2010-02-05, 20:13:00 »
Słowem wstępu, jeżeli chodzi o metody Monte Carlo, to główną ich zasadą jest "próbuj, próbuj, ..., a potem weż średnią i na pewno ci wyjdzie". Jeżeli zaś chodzi o przedstawiony tutaj problem to...
Weźmy pod uwagę kwadrat o boku RAND_MAX (w skrócie RM) (ile RAND_MAX wynosi, szczerze nas to guzik interesuje, byle było duże). Wyobraźmy sobie kwadrat, którego lewy dolny róg ma współrzędne (0,0) a prawy górny (RM, RM). W powyższej pętli n razy losujemy jakiś punkt o współrzędnych (x,y) leżący wewnątrz tego kwadratu (0 < x,y < RM). Polem tego kwadratu określmy natomiast liczbę wylosowanych punktów leżących wewnątrz tego kwadratu (a ponieważ wszystkie punkty tam się znajdują, więc pole kwadratu = liczba punktów = n). W kwadrat ów wpiszmy teraz koło - z podstaw matematyki wiemy, iż jego średnica równa będzie długości boku kwadratu, w którym został wpisany, czyli r (czyli jego promień = RM/2) natomiast jego pole = PI * promien^2 co daje Pi * (RM^2)/4 = PI * n/4. Porównując teraz ów dwa pola możemy dojść do wniosku, iż PI = 4*(pole koła / pole kwadratu) (co jest ładnie napisane w przytoczonym kodzie). Ponieważ, zgodnie ze statystyką i charakterysytką rozkładu liniowego zmiennej losowej, losowane punkty będą rozkładać się mniej więcej równomiernie w naszym kwadracie, więc obliczone PI możemy uznać za wartość zbliżoną do wartości rzeczywistej (oczywiście wartośc ta będzie tym mniej obarczona błędem im większa będzie liczba losowanych punktów (n)).
Mam nadzieję, iż wytłumaczyłem to w miarę zrozumiale :)

P.S.: Teraz dopiero doczytałem: w przytoczonym przykładzie losuje się punkty z przedziału (-0,5;-0,5)-(0,5;0,5) co daje nam RM=1, ale filozofia pozostaje ta sama ;)

chmooreck

  • Gość
monte carlo
« Odpowiedź #3 dnia: 2010-02-05, 21:37:33 »
Cytat: ZipoKing
P.S.: Teraz dopiero doczytałem: w przytoczonym przykładzie losuje się punkty z przedziału (-0,5;-0,5)-(0,5;0,5) co daje nam RM=1, ale filozofia pozostaje ta sama ;)
[-1;-1] - (1;1)  ;-)

Krzysiek1990

  • Gość
monte carlo
« Odpowiedź #4 dnia: 2010-02-05, 22:53:55 »
Tak. Teraz już rozumiem to dużo lepiej :) dzięki :)
A jeszcze mam takie pytanie.
Po co mi w wyrażeniach
x = ((double)rand() / (RAND_MAX)) * 2 - 1;
          y = ((double)rand() / (RAND_MAX))*2 - 1;
*2-1 na końcu skoro program działa tak samo bez nich?

I jak często się wykożystuję tą metodę w programowaniu?

.............EDIT.............
Cytat: chmooreck
Cytat: ZipoKing
P.S.: Teraz dopiero doczytałem: w przytoczonym przykładzie losuje się punkty z przedziału (-0,5;-0,5)-(0,5;0,5) co daje nam RM=1, ale filozofia pozostaje ta sama ;)
[-1;-1] - (1;1)  ;-)
Cytat: ZipoKing
Weźmy pod uwagę kwadrat o boku RAND_MAX (w skrócie RM)
RM=bok skoro bok jest równy 1 jednostce, to ZipoKing ma rację :)

ZipoKing

  • Gość
monte carlo
« Odpowiedź #5 dnia: 2010-02-05, 23:26:05 »
@chmooreck: rzeczywiście, masz rację; syndrom piątkowego wieczoru daje znać o sobie ;)
@Krzysiek1990, ów "* 2 - 1" istnieje po to, aby środek całego układu umieścić w punkcie (0,0) układu współrzędnych (czasami się to baaardzo przydaje, ale dlaczego tutaj, mimo iż jest to zupełnie niepotrzebne,  to pytanie dla autora zadania (być może tzw. skrzywienie zawodowe ;) ))

Krzysiek1990

  • Gość
monte carlo
« Odpowiedź #6 dnia: 2010-02-05, 23:33:00 »
No i teraz już w takim razie rozumiem.
Dzięki za wytłumaczenie :)
Pozdrawiam

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3056
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
monte carlo
« Odpowiedź #7 dnia: 2010-02-06, 20:05:37 »
To czy jest "...*2-1" czy nie daje nam albo MC z całego koła i kwadratu bądź z ćwiartki koła i ćwiartki kwadratu - co akurat w tym przypadku nie ma znaczenia, bo stosunek pól jest ten sam.
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy