簡體   English   中英

rand() 每次給出幾乎相同的數字

[英]rand() gives almost the same number every time

我正在學習 C,我想生成一個 0 到 6400 之間的數字。這是我想出的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand(time(0));
    int i = (rand() % 6401);
    printf("Random number between 0 and 6400: %d\n", i);
    return 0;
}

當我從命令行編譯並運行這段代碼時,我得到了一些非常奇怪的結果:

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6282

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6282

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6285

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6285

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6289

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6289

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6292

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6292

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6295

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6298

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6298

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6302

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6302

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6305

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6305

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6308

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6308

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6311

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6311

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6315

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6315

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6318

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6318

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6321

K:\C\Labo\Oefeningen 2019>

這些數字都不同,但我希望在 0 到 6400 之間有一個稍微均勻的分布。奇怪的是,我在一小時前使用相同的 function 沒有問題? (我以前用它來生成較小的數字。)我確定我錯過了一些非常愚蠢的東西,但我現在已經被困了一個小時。

編輯:我知道當您在同一秒內運行代碼時它會給出相同的值。 我在執行之間等待了幾秒鍾(10-20),但我仍然得到相同的結果? 這些值很少相同,它們只是 100% 的時間非常非常非常相似。 我該如何解決這個問題?

time()的分辨率為 1 秒。 因此,您的程序僅在平均經過半秒后才會生成不同的值。

如果您的編譯器支持 C11,則可以使用更高分辨率的 function、 timespec_get() 你的srand(time(0)); 然后將轉換為以下內容:

struct timespec ts;
timespec_get(&ts, TIME_UTC);
srand(ts.tv_nsec);

這里ts.tv_nsec是時間戳的納秒部分,其分辨率應該足以滿足您的目的。

如果您的編譯器不支持 C11,您仍然可以獲得比time()更好的隨機種子源,分辨率約為毫秒(實際分辨率由CLOCKS_PER_SEC宏給出): clock() function。 然后你的播種代碼將是

srand(clock());

請注意,它實際上可能是一個不好的熵源,尤其是在您的操作系統不忙的情況下,因此程序將以某種可預測的速度運行。 這是因為clock()時代的開始與程序的執行有關,而不是與實時有關。 例如,最好使用clock()time(0)的總和來獲得更多不可預測的值:

srand(time(0)+clock());

計算機並不會真正生成隨機數。 因此,當您在同一秒內執行兩次代碼時,它會返回相同的值。 為了獲得更好的結果,您可以在 srand 中添加 getpid() 的值。

請記住,這仍然不是真正的隨機。

如果您的rand被破壞,您可以嘗試其中一種xorshift偽隨機數生成器。 它們並不完美,但最終的實現非常短。 自己用可能就夠了。

這是一個實現示例:我使用這個作為參考。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>

uint64_t    xorshift64s(uint64_t seed)
{
    static uint64_t i = 1;

    if (seed != 0)
        i = seed;
    i ^= i >> 12;
    i ^= i << 25;
    i ^= i >> 27;
    i *= 0x2545f4914f6cdd1d;
    return (i >> 32);
}


int main()
{
    srand(time(0));
    int i = (rand() % 6401);
    printf("rand    : Random number between 0 and 6400: %d\n", i);
    xorshift64s(time(0));
    int j = (xorshift64s(0) % 6401);
    printf("xorshift: Random number between 0 and 6400: %d\n", j);
    return 0;
}

如果其他人遇到這個問題,我想我找到了解決方法。 我知道這不是一個完美的解決方案,但它是唯一對我有用的解決方案。 我認為我的編譯器中使用的隨機數生成器根本不喜歡類似的種子。 使用此代碼片段,它實際上會生成一些可接受的半隨機數:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand((unsigned int)time(0) * 100000000);
    int i = (rand() % 6401);
    printf("Random number between 0 and 6400: %d\n", i);
    return 0;
}

這是我從 btw 獲得垃圾箱編譯器的地方: http://tdm-gcc.tdragon.net/download

rand生成的數字並不是真正隨機的,它們是使用公式生成的。 這就是為什么播種是可能的和必要的。 根據使用的公式,種子和前幾個隨機數之間可能存在高度相關性。

解決方法是使用更好的公式(不是rand ),使用更隨機的種子,或者在播種后浪費一些隨機數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM