Tôi muốn bổ sung các câu trả lời xuất sắc của Angry Shoe và peterchen bằng một bản tổng quan ngắn về tình hình nghệ thuật trong năm 2015:
Một số lựa chọn tốt
randutils
Các randutils
thư viện (trình bày) là một sự mới lạ thú vị, cung cấp một giao diện đơn giản và (tuyên bố) khả năng ngẫu nhiên mạnh mẽ. Nó có những nhược điểm là nó làm tăng thêm sự phụ thuộc vào dự án của bạn và, là mới, nó chưa được thử nghiệm rộng rãi. Dù sao, miễn phí (giấy phép MIT) và chỉ có tiêu đề, tôi nghĩ nó đáng để thử.
Mẫu tối thiểu: một cuộn khuôn
#include <iostream>
#include "randutils.hpp"
int main() {
randutils::mt19937_rng rng;
std::cout << rng.uniform(1,6) << "\n";
}
Ngay cả khi ai không quan tâm đến thư viện, trang web ( http://www.pcg-random.org/ ) cung cấp nhiều bài viết thú vị về chủ đề sinh số ngẫu nhiên nói chung và thư viện C ++ nói riêng.
Boost.Random
Boost.Random
(tài liệu) là thư viện mà lấy cảm hứng C++11
's <random>
, mà cổ phiếu nhiều giao diện. Mặc dù về mặt lý thuyết cũng là một phần phụ thuộc bên ngoài, Boost
nhưng hiện tại có trạng thái là thư viện "gần chuẩn" và Random
mô-đun của nó có thể được coi là sự lựa chọn cổ điển cho việc tạo số ngẫu nhiên chất lượng tốt. Nó có hai ưu điểm đối với C++11
giải pháp:
- nó di động hơn, chỉ cần hỗ trợ trình biên dịch cho C ++ 03
- nó
random_device
sử dụng các phương pháp cụ thể của hệ thống để cung cấp hạt giống chất lượng tốt
Lỗ hổng nhỏ duy nhất là việc cung cấp mô-đun random_device
không chỉ có tiêu đề, người ta phải biên dịch và liên kết boost_random
.
Mẫu tối thiểu: một cuộn khuôn
#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>
int main() {
boost::random::random_device rand_dev;
boost::random::mt19937 generator(rand_dev());
boost::random::uniform_int_distribution<> distr(1, 6);
std::cout << distr(generator) << '\n';
}
Mặc dù mẫu tối thiểu hoạt động tốt, nhưng các chương trình thực nên sử dụng một số cải tiến:
- làm
mt19937
mộtthread_local
: trình tạo khá đầy đặn (> 2 KB) và tốt hơn là không được phân bổ trên ngăn xếp
- hạt giống
mt19937
với nhiều hơn một số nguyên: Mersenne Twister có trạng thái lớn và có thể tận dụng nhiều entropy hơn trong quá trình khởi tạo
Một số lựa chọn không quá tốt
Thư viện C ++ 11
Mặc dù là giải pháp thành ngữ nhất, nhưng <random>
thư viện không cung cấp nhiều để đổi lấy sự phức tạp của giao diện ngay cả đối với các nhu cầu cơ bản. Lỗ hổng nằm ở chỗ std::random_device
: Tiêu chuẩn không bắt buộc bất kỳ chất lượng tối thiểu nào cho đầu ra của nó (miễn là entropy()
trả về 0
) và, kể từ năm 2015, MinGW (không phải là trình biên dịch được sử dụng nhiều nhất, nhưng hầu như không phải là lựa chọn bí truyền) sẽ luôn in 4
trên mẫu tối thiểu.
Mẫu tối thiểu: một cuộn khuôn
#include <iostream>
#include <random>
int main() {
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(1, 6);
std::cout << distr(generator) << '\n';
}
Nếu việc triển khai không bị lỗi, giải pháp này sẽ tương đương với giải pháp Boost và áp dụng các đề xuất tương tự.
Giải pháp của Godot
Mẫu tối thiểu: một cuộn khuôn
#include <iostream>
#include <random>
int main() {
std::cout << std::randint(1,6);
}
Đây là một giải pháp đơn giản, hiệu quả và gọn gàng. Chỉ có khiếm khuyết, sẽ mất một khoảng thời gian để biên dịch - khoảng hai năm, cung cấp C ++ 17 được phát hành đúng hạn và randint
chức năng thử nghiệm được chấp thuận thành Tiêu chuẩn mới. Có thể đến lúc đó những đảm bảo về chất lượng hạt giống sẽ được cải thiện.
Mẫu tối thiểu: một cuộn khuôn
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(nullptr));
std::cout << (std::rand() % 6 + 1);
}
Giải pháp C cũ được coi là có hại và vì những lý do chính đáng (xem các câu trả lời khác tại đây hoặc phân tích chi tiết này ). Tuy nhiên, nó có những ưu điểm: đơn giản, dễ di chuyển, nhanh chóng và trung thực, theo nghĩa người ta biết rằng các số ngẫu nhiên mà người ta nhận được hầu như không phù hợp, và do đó người ta không muốn sử dụng chúng cho các mục đích nghiêm túc.
Giải pháp troll kế toán
Mẫu tối thiểu: một cuộn khuôn
#include <iostream>
int main() {
std::cout << 9; // http://dilbert.com/strip/2001-10-25
}
Mặc dù 9 là một kết quả hơi bất thường đối với một cuộn chết thông thường, nhưng người ta phải thán phục sự kết hợp tuyệt vời của những phẩm chất tốt trong giải pháp này, giải pháp này trở thành giải pháp nhanh nhất, đơn giản nhất, thân thiện với bộ nhớ cache nhất và di động nhất. Bằng cách thay thế 9 bằng 4, người ta sẽ có được một bộ tạo hoàn hảo cho bất kỳ loại Dungeon và Rồng nào chết, trong khi vẫn tránh được các giá trị chứa đầy biểu tượng 1, 2 và 3. Một lỗ hổng nhỏ duy nhất là, do tính khí tồi tệ của những kẻ thích tính toán của Dilbert, chương trình này thực sự tạo ra hành vi không xác định.