2013-04-14 17 views
10

postanowiłem poznać C++ 11 <random> lepiej, więc napisałem taki kod:std :: piecewise_linear_distribution nie działa pod VS2012?

std::mt19937 gen(10); 
std::piecewise_linear_distribution<> d(Range.begin(), Range.end(), 
             RangeValues.begin()); 

std::map<int, unsigned int> hist; 
for (int n = 0; ++n != iterations;) 
    ++hist[std::round(d(gen))]; 

for (auto p : hist) 
    std::cout << std::setw(2) << p.first << ": " 
      << std::string(p.second/(iterations/200), '*') << '\n'; 

std::random_device jakiegoś powodu wydaje się nie działać na Coliru, więc wszedłem nasienie próbki zamiast const. Zakładam, że to UB, stąd IIRC opiera się głównie na sprzęcie i dlatego nie jest obsługiwane przez Coliru (popraw mnie jeśli się mylę). W Ideone działa jednak.

Potem przeniósł go uruchomić na VS2012, jedyna różnica polega na własnej realizacja std::round:

return number < 0.0 ? std::ceil(number - 0.5) : std::floor(number + 0.5); 

To działa doskonale na Coliru poprawne, ale kiedy mogę skompilować i uruchomić go na VS2012, the output is just wrong.

Każdy pomysł, jak to poprawić, a co ważniejsze, dlaczego tak się dzieje? Czy robię coś opóźnionego, czy też VS2012 nie jest tutaj inteligentnym?

+1

["std :: round'] (http://en.cppreference.com/w/cpp/numeric/math/round) jest zadeklarowane w nagłówku '', FYI. Zakładam, że właśnie dlatego napisałeś własną wersję (kompilator nie mógł jej znaleźć). –

+0

Nie. Nawet gdy dodaję '', pojawia się błąd: 'round': nie jest członkiem' std'. – Wierzba

Odpowiedz

7

Wygląda na to, że jest to problem Visual Studio. Wypróbowałem poniższy program (zaadaptowany z PO), a wyniki generowane przez GCC 4.7.2, Clang 3.2 i Intel 13.1.0 są bardzo rozsądne, natomiast wygenerowany przez Visual Studio Nov 2012 CTP jest zupełnie inny.

Gęstość prawdopodobieństwa jest jednostajnie liniowa i definiowana przez tablice x i p w następujący sposób. Wykonywana jest odcinkowo liniowa funkcja łącząca punkty (x [i], p [i]) dla i = 0, ..., N (gdzie N = x.size() - 1). Następnie funkcja ta jest znormalizowana (poprzez podzielenie jej całką), aby uzyskać gęstość prawdopodobieństwa.

#include <iostream> 
#include <iomanip> 
#include <string> 
#include <random> 
#include <array> 

int main() { 

    std::mt19937 gen(10); 

    std::array<double, 3> x = {{0, 20, 40}}; 
    std::array<double, 3> p = {{0, 1, 0}}; 
    std::piecewise_linear_distribution<> dist(x.begin(), x.end(), p.begin()); 

    std::array<int, 40> hist = {{0}}; 

    for (size_t i = 0; i < 200000; ++i) 
     ++hist[static_cast<size_t>(dist(gen))]; 

    for (size_t n = 0; n < hist.size(); ++n) 
     std::cout << std::setfill('0') << std::setw(2) << n << ' ' << 
      std::string(hist[n]/200, '*') << std::endl; 

    std::cout << "\nValues in interval [20, 21[ : " << hist[20] << std::endl; 
} 

W naszym przykładzie funkcja wieloboków łączy się (0, 0), (20, 1) i (40, 0). W związku z tym jego kształt jest trójkątem równoramiennym z podstawą 40 ​​i wysokością 1, co daje obszar 20. W związku z tym gęstość prawdopodobieństwa f łączy się (0, 0), (20, 1/20) i (40, 0). Oznacza to, że w przedziale [20, 21 [możemy spodziewać się około f (20) * (21 - 20) = 1/20 * 1 = 1/20 wyników losowania. Łącznie wyciągamy 200 000 wartości, a następnie możemy się spodziewać około 10 000 punktów w [20, 21 [.

GCC, dzyń i Intel raport 9734 punktów w [20, 21 [i wyświetlić wzór, który jest bardzo podobny do trójkąta równoramiennego:

00 * 
01 *** 
02 ***** 
03 ******** 
04 *********** 
05 ************** 
06 *************** 
07 ****************** 
08 ******************** 
09 ************************ 
10 ************************** 
11 **************************** 
12 ******************************* 
13 ********************************* 
14 *********************************** 
15 *************************************** 
16 ***************************************** 
17 ****************************************** 
18 ********************************************** 
19 ************************************************ 
20 ************************************************ 
21 ********************************************* 
22 ******************************************* 
23 ***************************************** 
24 ************************************** 
25 ************************************ 
26 ********************************** 
27 ****************************** 
28 **************************** 
29 ************************** 
30 *********************** 
31 ******************** 
32 ****************** 
33 **************** 
34 ************* 
35 *********** 
36 ********* 
37 ****** 
38 *** 
39 * 

Values in interval [20, 21[ : 9734 

Niestety, Visual Studio listopada 2012 CTP daje to:

00 ********************************************** [truncated] 
01 ********************************************** 
02 *********************************** 
03 ***************************** 
04 ************************** 
05 *********************** 
06 ********************* 
07 ******************** 
08 ******************* 
09 ****************** 
10 ***************** 
11 **************** 
12 *************** 
13 ************** 
14 ************** 
15 ************** 
16 ************* 
17 ************* 
18 ************* 
19 ************ 
20 ************ 
21 ************* 
22 ************* 
23 ************* 
24 ************* 
25 ************** 
26 *************** 
27 *************** 
28 **************** 
29 ***************** 
30 ****************** 
31 ******************* 
32 ******************* 
33 ********************* 
34 *********************** 
35 ************************** 
36 ***************************** 
37 *********************************** 
38 ********************************************** 
39 ********************************************** [truncated] 

Values in interval [20, 21[ : 2496 

Uwagi:

  1. mam obcięty wyjście Visual Studio dla lepszego wyświetlania.
  2. Lepsze oszacowanie liczby punktów w [20, 21 [wynosi 200 000 * (0,5 * (f (20) + f (21)) * (21 - 20) = 100 000 * (1/20 + 1/20 - 1/400) = 10 000 - 250 = 9750.
+3

Ironiczne, że wizualne wyjście twojego programu zostanie zepsute na wyjściu jedynego toolchaina, który rzekomo ma cokolwiek wspólnego z "wizją"! –

+2

Aha, więc błąd biblioteki. To powinno zostać przekazane państwom członkowskim. –

+0

To uspokaja, że ​​nie jestem złym, złym człowiekiem. Yay. Zamierzam od teraz kodować rzeczy w C++ 11 tylko na gcc. Przesłano do firmy Microsoft. – Wierzba