2013-04-14 23 views
10

tôi quyết định để làm quen với C++ 11 <random> tốt hơn, vì vậy tôi đã viết một mã số ví dụ:std :: piecewise_linear_distribution không hoạt động theo 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'; 

Đối với một số lý do std::random_device dường như không hoạt động trên Coliru, vì vậy tôi bước vào một hạt giống mẫu const để thay thế. Tôi đoán, đó là UB do đó IIRC nó dựa rất nhiều vào phần cứng, và đó là lý do tại sao nó không được hỗ trợ trên Coliru (đúng tôi nếu tôi sai). Trên Ideone nó hoạt động tuy nhiên.

Sau đó, tôi chuyển nó để chạy trên VS2012, sự khác biệt chỉ là một thực hiện riêng của std::round:

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

Nó hoạt động hoàn toàn chính xác trên Coliru, nhưng khi tôi biên dịch và chạy nó trên VS2012, the output is just wrong.

Bất kỳ ý tưởng nào về cách sửa lỗi này và quan trọng hơn, tại sao điều đó xảy ra? Tôi có đang làm điều gì đó chậm phát triển, hoặc là VS2012 không phải là người thông minh ở đây không?

+1

['std :: round'] (http://en.cppreference.com/w/cpp/numeric/math/round) được khai báo trong tiêu đề '', FYI. Tôi đoán đó là lý do tại sao bạn đã viết phiên bản của riêng bạn (trình biên dịch không thể tìm thấy nó). –

+0

Không. Ngay cả khi tôi bao gồm '', tôi nhận được một lỗi: 'round': không phải là thành viên của' std'. – Wierzba

Trả lời

7

Dường như đây là vấn đề về Visual Studio. Tôi đã thử chương trình dưới đây (được điều chỉnh từ OP) và đầu ra được tạo ra bởi GCC 4.7.2, Clang 3.2 và Intel 13.1.0 rất hợp lý trong khi phiên bản được tạo ra bởi Visual Studio Nov 2012 CTP hoàn toàn khác.

Mật độ xác suất là tuyến tính từng phần và được xác định bởi mảng x và p theo cách sau. Một hàm tuyến tính nối tiếp các điểm (x [i], p [i]) cho i = 0, ..., N (trong đó N = x.size() - 1) được xây dựng. Sau đó, chức năng này được chuẩn hóa (bằng cách chia nó cho tích phân của nó) để lấy mật độ xác suất.

#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; 
} 

Trong ví dụ của chúng tôi, hàm đa giác kết nối (0, 0), (20, 1) và (40, 0). Do đó, hình dạng của nó là một tam giác cân với cơ số 40 và chiều cao 1 có diện tích là 20. Do đó, mật độ xác suất f kết nối (0, 0), (20, 1/20) và (40, 0). Điều này ngụ ý rằng trong khoảng [20, 21 [chúng ta có thể mong đợi khoảng f (20) * (21 - 20) = 1/20 * 1 = 1/20 kết quả của trận hòa. Tổng cộng, chúng tôi rút ra 200.000 giá trị và sau đó, chúng tôi có thể mong đợi khoảng 10.000 điểm trong [20, 21 [.

GCC, Clang và Intel báo cáo 9734 điểm trong [20, 21 [và hiển thị một mô hình khá giống với một tam giác cân:

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 

Thật không may, Visual Studio tháng 11 năm 2012 CTP cho này:

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 

Ghi chú:

  1. tôi đã ra Visual Studio cắt ngắn để hiển thị tốt hơn.
  2. Ước tính tốt hơn cho số điểm trong [20, 21 [là 200.000 * (0,5 * (f (20) + f (21))) * (21 - 20) = 100.000 * (1/20 + 1/20 - 1/400) = 10.000 - 250 = 9750.
+3

Trớ trêu thay rằng đầu ra trực quan của chương trình của bạn sẽ bị phá vỡ trong đầu ra của chuỗi công cụ duy nhất mà purports có bất cứ điều gì để làm với "tầm nhìn" nào! –

+2

Aha, vì vậy lỗi thư viện. Điều đó nên được nộp cho MS. –

+0

Vâng, điều này giải quyết rằng tôi không phải là một người xấu, xấu. Yay. Mã Gonna C++ 11 nội dung trên gcc chỉ từ bây giờ trở đi. Đã gửi cho Microsoft. – Wierzba

Các vấn đề liên quan