我使用rand()
作爲需要唯一值的6位字段。我做對了嗎?C中的rand()有多獨特?
什麼是賠率,rand()
可以給我連續或頻繁的電話相似的價值?
當我使用rand()時它是唯一的。但是,當我撥打srand(time(NULL))
或srand(clock())
時,返回相同的號碼。看起來,就像它對我來說正好相反。或者是?
我使用rand()
作爲需要唯一值的6位字段。我做對了嗎?C中的rand()有多獨特?
什麼是賠率,rand()
可以給我連續或頻繁的電話相似的價值?
當我使用rand()時它是唯一的。但是,當我撥打srand(time(NULL))
或srand(clock())
時,返回相同的號碼。看起來,就像它對我來說正好相反。或者是?
正如其他人所指出的那樣,唯一性並不能保證。但是,您可能會看到重複的數字,因爲您錯誤地使用了srand()和rand()。
srand()用於播種隨機數發生器。這意味着在調用srand之後對rand()的一系列調用將產生特定的一系列值。如果調用函數srand()使用相同的值,則RAND()會產生相同的一系列值(對於給定的實現,有不同的實現之間沒有擔保)對我來說這
int main() {
srand(100);
for(int i = 0; i<5; ++i)
printf("%d\n",rand());
printf("\nreset\n\n");
srand(100);
for(int i = 0; i<5; ++i)
printf("%d\n",rand());
}
生產:
365
1216
5415
16704
24504
reset
365
1216
5415
16704
24504
time()和clock()會返回時間,但是如果您足夠快地調用它們,則返回的值將相同,因此您將從rand()中獲得相同的一系列值。
此外,rand()通常不是一個非常好的隨機數生成器,使用它通常意味着您必須將一系列數字轉換爲您實際需要的分佈。你應該找到一種不同的隨機來源,要麼學習合適的方法來產生你想要的發行版,要麼使用一個可以爲你做的發行版。 (例如,生成0到N之間的「隨機」數字的一種常見方法是做rand() % N
,但這並不是最好的方法。
C++在<random>
中提供了一個好得多的隨機數字庫。它提供了不同的PRNG算法,如linear_congruential,mersennne_twister,甚至可能還有一個密碼安全的RNG(取決於實現)。它還提供用於生成各種分發的對象,例如uniform_int_distribution,它應避免rand() % N
中出現的錯誤。
rand()
返回0到RAND_MAX
之間的值。由於它是一個分散的均勻分佈,因此重複數字的概率爲1 /(RAND_MAX
+1),因此不保證唯一性。
srand(seed)
初始化您的隨機數發生器,以便從rand()
獲得號碼的順序是你每次seed
初始化它給予相同的每一次。
在您的例子seed = time(NULL)
其是從1月1日起經過的秒數,1970從而確保不同的種子,從而隨機數的不同的序列對每次調用srand(time(NULL))
(假定它不是在相同的第二製造) 。
隨機數字是隨機,而不是唯一。就像擲骰子的情況一樣,當你連續擲出幾個六分球時,你的rand
可以(也應該)有時會給你帶來相同的數字。
爲了確保數字是唯一的,請建立一個註冊已添加的每個數字的集合。當一個隨機數字出現不止一次時,扔第二個,然後去下一個。
你應該只調用'srand'一次。這就是僞隨機數序列的種子。 – chris
RAND_MAX需要15個「有效位」。在最糟糕的實現中,只有32K個不同的值。好消息是:現在大多數實現都比較好。 – wildplasser
@wildplasser雖然合理的'rand()/ srand()'執行您的[評論](http://stackoverflow.com/questions/12412108/how-unique-is-rand-in-c/12412168#comment16682299_12412108),不幸的是,C沒有指定「只有(至少)32K個不同的值」,只有值的範圍 - 它們不需要全部發生。 – chux