在知乎上看到老趙回答了 你在編程時見過最愚蠢的 Bug 是什麼?
首先是段JS代碼:
var number = 10;
var showNumber = function () {
alert(number);
}
(function () {
number = 20;
showNumber();
})()
不要運行,猜猜看這段代碼會alert出什麼結果來?
答案是:10。好吧,為什麼不是20?
再來一段.NET的:
var numbers = new int[10];
// 生成10個隨機數
for (var i = 0; i < numbers.Length; i++) {
numbers[i] = new System.Random().Next();
}
生成10個隨機數,盡管每次運行結果都不同,但為什麼每次這10個數字都是相同的?
其中第一js是因為沒在showNumber後面(第四行)加“;”;
第二.NET的隨機數這個問題我倒是沒遇到過,幾乎每次只會用一個不會一次調用多個,所以沒注意。
先看看msdn怎麼說:
Random構造函數Random()
使用與時間相關的默認種子值,初始化 Random 類的新實例。
The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers.This problem can be avoided by using a single Random object to generate all random numbers. You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor. (英語不好,就貼原文了)
Random的種子利用的是系統時鐘種子。而Windows系統時鐘的更新頻率大概在10ms左右(各個版本不一樣),而這個for循環的執行顯然要快得多,那每次利用的就是同一個種子,種子相同,Random產生相同的隨機數(即使實例不同也一樣)。所以返回的10個值都是一樣的了。
解決方法:
第一種利用Thread.Sleep讓線程休眠一段時間(時間大於Windows系統時鐘的更新頻率),這個不推薦使用。
第二種將初始化移出循環:
var numbers = new int[10];
// 初始化Random
System.Random rd = new System.Random();
for (var i = 0; i < numbers.Length; i++)
{
numbers[i] = rd.Next();
}
參考文檔:
MSDN:Random 類
Random的實現原理