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.

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

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õ.

#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 :smile:

#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.

1 Like

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

1 Like

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é :slight_smile:

1 Like

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…

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?