2013-08-12 24 views
9

Próbuję przetłumaczyć część kodu Pythona na C++. To, co robi kod, to uruchomienie symulacji Monte Carlo. Myślałem, że wyniki z Pythona i C++ mogą być bardzo bliskie, ale wydaje się, że stało się coś śmiesznego.Różnica między generowaniem liczb losowych C++ a Pythonem

Oto co mam zrobić w Pythonie:

self.__length = 100 
self.__monte_carlo_array=np.random.uniform(0.0, 1.0, self.__length) 

Oto co mam zrobić w C++:

int length = 100; 
std::random_device rd; 
std::mt19937_64 mt(rd()); 
std::uniform_real_distribution<double> distribution(0, 1); 

for(int i = 0; i < length; i++) 
{ 
    double d = distribution(mt); 
    monte_carlo_array[i] = d; 
} 

Pobiegłem powyżej generowania liczb losowych 100x5 razy zarówno w Pythonie i C++, a następnie do symulacji monte carlo z tymi liczbami losowymi.

W symulacji Monte carlo ustawiam próg na 0,5, dzięki czemu mogę z łatwością sprawdzić, czy wyniki są równomiernie rozłożone.

Oto koncepcyjny projekt, co robi symulacji Monte Carlo:

for(i = 0; i < length; i++) 
{ 
    if(monte_carlo_array[i] > threshold) // threshold = 0.5 
     monte_carlo_output[i] = 1; 
    else 
     monte_carlo_output[i] = 0; 
} 

Od długości tablicy jest Monte Carlo 120, I spodziewać się 60 1 s zarówno w Pythonie i C++. Obliczyłem średnią liczbę 1 s i odkryłem, że chociaż średnia liczba w C++ i Pythonie wynosi około 60, ale trend jest silnie skorelowany. Ponadto średnia liczba w Pythonie to zawsze wyższa niż w C++.

distribution chartCzy mogę wiedzieć, czy to dlatego, że zrobiłem coś złego, czy jest to po prostu różnica między mechanizmami generowania losowego w C++ i Pythonie?

[edytuj] Należy pamiętać, że RNG in Python jest również Mersenne Twister 19937.

+1

Różne generatory liczb losowych dają różne zestawy liczb losowych. Spodziewałbym się, że jeśli uruchomisz go kilka razy (jak setki razy), dostrzeżesz mniej oczywistą różnicę. –

+2

Czy to naprawdę widać z kodu, który wyświetlasz? Muszą być inne wejścia, w przeciwnym razie nie byłoby żadnej korelacji między kodami! Podejrzewam, że błąd jest gdzie indziej ... –

+0

Te szwy wyników zmanipulowane ... –

Odpowiedz

5

Napisałem to na podstawie kodu pisał:

import numpy as np 

length = 1000 
monte_carlo_array=np.random.uniform(0.0, 1.0, length) 
# print monte_carlo_array 
threshold = 0.5 
above = 0 

for i in range (0,length): 
    if monte_carlo_array[i] > threshold: 
     above+=1 
print above 

i to w C++:

#include <random> 
#include <iostream> 

int main() 
{ 
    const int length = 1000; 
    std::random_device rd; 
    std::mt19937_64 mt(rd()); 
    std::uniform_real_distribution<double> distribution(0, 1); 
    double threshold = 0.5; 
    double monte_carlo_array[length]; 

    for(int i = 0; i < length; i++) 
    { 
     double d = distribution(mt); 
     monte_carlo_array[i] = d; 
    } 
    int above = 0; 

    for(int i = 0; i < length; i++) 
    { 
     if (monte_carlo_array[i] > threshold) 
     { 
      above++; 
     } 
    } 
    std::cout << above << std::endl; 
} 

Po pięć serii:

Python: 
480 
507 
485 
515 
506 
average: 
498.6 

C++: 
499 
484 
531 
509 
509 
average 
506.4 

Więc jeśli cokolwiek znajdę, że C++ jest wyższa niż python. Ale myślę, że to bardziej przypadek "losowe liczby nie są równomiernie rozłożone z małą liczbą próbek".

Zmieniłem długość do 100000 zamiast, a jeszcze wyniki różnią się w górę iw dół około 50k:

Python: 

50235 
49752 
50215 
49717 
49974 

Average: 
49978.6 

C++: 

50085 
50018 
49993 
49779 
49966 

Average: 
49968.2 

Podsumowując, nie sądzę, że jest jakaś ogromna różnica między losowymi implementacjach liczba w C++ i Python jeśli chodzi o "jak jednolite jest to około 0,5". Ale nie bardzo studiowałem statystyki (i to było wiele lat temu).

+0

Cześć, maty. Bardzo dziękuję za odpowiedź. Całkowicie się z tobą zgadzam, że przy dużej próbie nie może być żadnej dużej różnicy. Jednak w praktyce nie generuję nawet tablicy o długości 1000, ale o wartości 120. Rozsądnie jest dostrzec różnicę. W praktyce wynik monte carlo jest mnożony przez liczbę losową z zakresu, a zakres jest taki sam dla Pythona i C++. int amount = 0; for (i = 0; i <120; i ++) amount + = monte_carlo_output * random_number; Jednak, co mnie przekonuje, to to, że Python zawsze pokonuje C++ pod względem wartości. – ChangeMyName

+0

Jest tak prawdopodobnie dlatego, że biegłeś tylko 5 razy. Przepisałem powyższy kod, aby wykonać serie 120, i chociaż zmiana jest większa, wynik jest nadal taki, że otrzymuję około 60 "powyżej 0,5" - ale to się zmienia. Właśnie zrobiłem 10000 przebiegów w pythonie, i wynosi on od 40 do 79 liczb powyżej 0,5. W C++, na jednym przykładzie, mam od 42 do 80. Innymi słowy, jeśli robisz to samo w C++ i w Pythonie, powinieneś otrzymać ten sam wynik (i masz te same generatory liczb losowych, które mam - to jest oczywiście całkowicie możliwe, jeśli używasz, powiedzmy, na komputerze z systemem Windows, którego nie masz) –

0

Gdy nie masz pewności, w liczbach losowych po prostu wygeneruj dużą liczbę losowych liczb za pomocą usługi takiej jak Random ORG. Po tej dostawie liczba ta jest liczona jako tablica w obu implementacjach (C++ i Python). W ten sposób będziesz mieć pewność, że oba programy używają tego samego zestawu liczb losowych, a będziesz mógł potwierdzić, że reszta kodu jest OK.