Vấn đề về hàm ngẫu nhiên trong C

Chào các bạn!
Do lười nhập mảng để test nên mình tạo 1 hàm sinh số ngẫu nhiên. Nhưng có một vấn đề là khi dùng hàm đấy để tạo 4 mảng khác nhau thì lại được 4 mảng giống nhau. Cho minh hỏi là có cách nào sinh số ngẫu nhiên trong c mà thật sự ngẫu nhiên không?
Đây là code hàm sinh số ngẫu nhiên của mình

int mangnguyen(int n, int mang1[])  //tao mang so nguyen tu -100->100
{
    int i;
    srand(time(NULL));
    for (i=0;i<n;i++)
        {
            mang1[i]=rand()%200-100 ;
}
     return(1);
}

Bạn nên srand 1 lần ở ban đầu thôi :3
Đơn giản là vì chương trình chạy nhanh quá
Mà time(NULL) trả về số giây -> nhiều khi chưa hết 1 giây chương trình lại gọi là mangnguyen, từ đó srand sử dụng số giây giống nhau vài lần -> srand sử dụng seed giống nhau.

Mà srand thì là một hàm giả ngẫu nhiên, nó chỉ lấy seed nhận vào và áp dụng công thức rồi sinh ra những số kế tiếp. Nên từ đó chương trình của bạn sinh ra những mảng giống nhau.

7 Likes

Win API thôi :slight_smile: hay /dev/random.

3 Likes

Đầu tiên bạn chạy time(NULL) 1 lần rồi lưu giá trị của nó, sau đó cứ mỗi lần tạo mảng thì bỏ giá trị của nó vào srand nhưng phải cộng thêm 1 mỗi lần.
C++ SDK hiện đại có header < random> tốt hơn nhiều.

3 Likes

Bạn có thể hardcode seed vào để demo mà :smiley: (lấy của số pi, e hay căn 2, 3, 5, 7, …)

Đến mức này thì hàm rand() không nên dùng (do vẫn có pattern), nên đổi. Lúc này true random chỉ dùng để lấy seed, khi PRNG tốt nghĩa là các phân bổ cũng tốt.

3 Likes

Cách này cũng hay đấy. Tuy không phải là random thật sự những cũng giải quyết được vấn đề về hàm của mình. Cảm ơn bạn nhiều nhá! Mà nếu có thể thì sao mình không cộng luôn giá trị random vừa tạo làm seed nhở :thinking:

Nhiều từ ngữ chuyên môn quá. Gà mờ như mình không hiểu được :rofl:

thế cũng được, miễn là bạn làm sao cho mỗi lần gọi srand thì seed phải luôn khác nhau.

Một trong những cách mình tạo unique seed:

  • Lấy PID của process hiện tại
srand(get_pid());
// GCC, MSVC có intrinsic riêng

#if defined(_WIN32)
    #include <intrin.h> 
#elif defined(__linux__) && !defined(__ANDROID__)
    #include <x86intrin.h>
#endif

...
srand(__rdtsc());

Tốt hơn sử dụng thời gian làm seed.

// Edit: Không nhớ srand() có nhận 64-bit làm seed không vì __rdtsc() trả về 64-bit

4 Likes

Và đừng dùng rand() :smiley: khi đã nghĩ đến seed như thế nào rồi.

1 Like

OP dùng rand() nên ví dụ rand() luôn cho đơn giản. Bình thường mình dùng

static std::mt19937 mt19937(__rdtsc());

C làm gì có std? :smiley:

Từ khóa là GoodPracticeRNG.

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