30/09/2018, 22:12

Hỏi về cách lập ct sinh ra 1 số ngẫu nhiên trong c++

E đang học khóa học c++ cho người mới bắt đầu… Ở phần bài tập của bài if statement có câu hỏi yêu cầu viết có sinh ra 1 số ngẫu nhiên từ 0 tới 100… Mà ở các bài trc đó mình chưa thấy đề cập tới phần này… có ai giúp mình với… Mình là người mới học nên chưa biết.

Ha manh Trung viết 00:23 ngày 01/10/2018

Ko biết ở các bài sau có ko… Nếu ko thì mong m.n giúp

Lưu Thành Vương viết 00:14 ngày 01/10/2018

Khai báo thư viện time.h rồi dùng hàm rand();
VD:

#include<time.h>
...
int main(){
    int n;
    srand(time(NULL));
    n=rand();  //  n between 0 and RAND_MAX
}

Muốn lấy giá trị ngẩu nhiên trong khoảng thì kết hợp với chia lấy dư (%) rồi + - gì đó .
Hình như có khai báo thư viện stdlib.h nữa không nhớ rõ.

Bùi Tống Minh Châu viết 00:19 ngày 01/10/2018
#include <iostream>

int main () {
    int n;
    n = n % 101;
    std::cout << n;
    system("pause");
    return 0;
}

cái này dành cho người chưa học rand. Cho vui tí thôi chứ cái này không nên dùng

#include <iostream>
#include <ctime>

int main () {
    srand(time(0));
    int n = rand() % 101;
    std::cout << n;
    system("pause");
    return 0;
}

Cái này dành cho người đã học rand.

Nguyễn Hoàng Trung viết 00:26 ngày 01/10/2018

Cái chia là sao bác @@ em chưa hiểu lắm

Do Ngoc Anh viết 00:15 ngày 01/10/2018

Cái chia là sao bác @@ em chưa hiểu lắm

Cái đó không phải chia, bạn cứ hiểu đó là một phần của cú pháp random đi, bạn xem video của anh đạt để hiểu thêm nhé

viết 00:17 ngày 01/10/2018

nếu muốn hàm random range tốt thật sự thì nên xài mấy hàm trong thư viện C++11 <random> ấy.

chạy cái code này trên g++ là thấy: http://ideone.com/d8UhWw

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <random>
#include <chrono>

int randomRange(int a, int b)
{
    return rand()%(b-a) + a;
}

int randomRange11(int a, int b, std::mt19937& gen)
{
    std::uniform_int_distribution<> dis(a, b);
    return dis(gen);
}

int main()
{
    srand(time(0));
    
    int a = 0;
    int b = 1000000000;
    int c = 100000000;
    int n = 10000;
    
    std::cout << "C rand() with modulo, RAND_MAX = " << RAND_MAX << "\n";
    int freq[10] = {0};
    for (int i = 0; i < n; ++i)
        freq[randomRange(a,b)/c]++;
    for (int i = 0; i < 10; ++i)
        std::cout << i << "e8-" << (i+1) << "e8: " << freq[i] << "\n";
        
        
    std::cout << "\nC++11 uniform_int_distribution\n";
    std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
    int freq11[10] = {0};
    for (int i = 0; i < n; ++i)
        freq11[randomRange11(a,b,rng)/c]++;
    for (int i = 0; i < 10; ++i)
        std::cout << i << "e8-" << (i+1) << "e8: " << freq11[i] << "\n";
}

output

C rand() with modulo, RAND_MAX = 2147483647
0e8-1e8: 1395
1e8-2e8: 1152
2e8-3e8: 900
3e8-4e8: 896
4e8-5e8: 905
5e8-6e8: 999
6e8-7e8: 951
7e8-8e8: 968
8e8-9e8: 900
9e8-10e8: 934

C++11 uniform_int_distribution
0e8-1e8: 1039
1e8-2e8: 1003
2e8-3e8: 959
3e8-4e8: 997
4e8-5e8: 1011
5e8-6e8: 978
6e8-7e8: 1020
7e8-8e8: 937
8e8-9e8: 1040
9e8-10e8: 1016

tại sao lại có chuyện ko đồng đều khi xài modulo thì lý do là vì rand() random từ 0 tới 231 - 1 nói chung là 2.147 tỷ mấy Nếu lấy rand() modulo cho 1 tỷ thì với 4 tỷ số đầu ok (giả sử là nó ngẫu nhiên “hoàn hảo”), nhưng 0.147 tỷ số sau 4 tỷ sẽ gây ra mất cân bằng. Nói chung là modulo số càng gần với RAND_MAX thì càng mất cân bằng. Trong C thì RAND_MAX chỉ cần >= 32767. VC++ làm vừa đúng yêu cầu luôn, nên % 1 tỷ ko được, mà % 10k là vấn đề lồ lộ rồi.

với std::uniform_int_distribution thì sẽ ko có chuyện này. Nhưng vấn đề phức tạp hơn vì đòi phải có 1 cái random number generator. Thông thường xài std::mt19937 là đủ, nhưng seed cho nó rất là khó nhớ so với srand. 1 cách khác là xài std::random_device làm generator, nhưng nó chậm, nên thường chỉ xài nó làm seed cho mt19937, nhưng lại có vấn đề khác là tiêu chuẩn ko yêu cầu random_device là non-deterministic generator, nên ko phải lúc nào cũng xài random_device được…

Bài liên quan
0