2012-01-18 93 views
1

爲了澄清,多個學生對象和他們都獲得相同的價值。隨機不工作

我知道這個問題已經被問過,但我沒有與其他職位有關他的話題的運氣。我有一個從1到3的隨機數字發生器。然後,我們使用%2來使布爾值爲真或假。每次我運行程序時,我都會得到全部真實或全部假。這是我的代碼。我知道隨機並不是真正的隨機。我能做些什麼來獲得更多的隨機數字。

Random random = new Random(); 

public Student() 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
} 

public bool readingLevel()//this always returns one value for the entire program. 
{ 
    return level; 
} 
+0

你是怎麼學習這門課的? – 2012-01-18 23:01:45

+0

你是否在循環中使用它? – 2012-01-18 23:01:51

+0

請提供一個完整的示例。 – 2012-01-18 23:03:06

回答

7

你只分配一個隨機值「級別」的構造過程中一次,所以它總是有初始值。 嘗試:

public bool readingLevel() 
{ 
    return (random.Next(1,3) % 2 == 0); 
} 

編輯:

Static Random random = new Random(); 
... 
+1

鑑於上下文,我假設(是的,假設)他有多個學生,他們都獲得相同的價值。我相信他的意圖是讓學生有一個不變的「水平」。 – 2012-01-18 23:03:51

+0

我正試圖讓不同的值有多個學生。我一直認爲每次創建新對象時都會調用構造函數。如果是這種情況,那麼不應該每個對象都有不同的值嗎? – Aaron 2012-01-18 23:30:52

+0

@Aaron在這種情況下,你應該爲這個類使用一個靜態的隨機數字生成器,因爲它表明每個學生正在使用相同的種子值創建導致你的問題。請參閱編輯 – 2012-01-18 23:37:04

-1
Random random = new Random(DateTime.Now.Ticks); 
+2

默認的構造函數已經按時間播種了。 – CodesInChaos 2012-01-18 23:04:45

+0

嗯,我想你每天都會學到新的東西:) – neeKo 2012-01-18 23:06:46

2
public Student() 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
} 

看起來非常像的Student類的構造函數。在這個構造函數中,你基本上是計算一個隨機數並將其存儲在level字段中。因此,如果在整個程序中使用相同的Student實例並在此實例上多次調用readingLevel()方法,它顯然會返回相同的值 - >在構建此實例期間完成的那個值,並且您存儲在level領域。

所以,你可能會考慮隨機數生成邏輯移動到readingLevel()方法,而不是簡單地在返回相同的數值一遍又一遍:

public class Student 
{ 
    private Random random = new Random(); 

    public bool readingLevel() 
    { 
     int randomLevel = random.Next(1,3); 
     return (randomLevel % 2 == 0); 
    } 
} 

現在每次調用此方法在同一個情況下,你應該得到一個新的隨機數的計算。

2

僅創建Random的一個實例並重新使用它。在快速連續種子中創建多個隨機數的實例,以獲得相同的值,從而產生相同的序列。

如果你的代碼在單線程中,你可以簡單地使用一個靜態屬性來保存Random的實例。

默認的種子值是從系統時鐘導出的,並具有有限的分辨率。因此,通過對默認構造函數的調用而緊密連續創建的不同Random對象將具有相同的默認種子值,因此將生成相同的隨機數集合。通過使用單個隨機對象來生成所有隨機數,可以避免此問題。您還可以通過修改由系統時鐘返回的種子值來解決此問題,然後將此新種子值明確提供給Random(Int32)構造函數。有關更多信息,請參閱Random(Int32)構造函數。

http://msdn.microsoft.com/en-us/library/h343ddh9.aspx

+0

雖然這顯然是真的,但這不是他的問題的原因。 – 2012-01-18 23:03:29

+0

@NoonSilk爲什麼?除了這個問題,每個「學生」實例都會有自己的閱讀水平。 – CodesInChaos 2012-01-18 23:05:16

+0

這可能是我誤解了他的問題的規範。 – 2012-01-18 23:06:42

0

您正在使用的隨機模擬真/假的情況,所以您要限制結果爲1或2。鑑於您對結果做一個奇/​​偶測試,你可能會更好做:

int randomLevel = random.Next(); 
level = (randomLevel % 2 == 0); 

此外,如果你創建你所有的學生接二連三有一個很好的機會,你當前的代碼將返回相同的值用於隨後的通話。

0

好吧。

想想這裏發生了什麼。當您的Student構建時,您會得到一些隨機數,然後將其設置爲成員變量level

然後,在其他點上,您可以調用一個函數readingLevel,它返回此前設置的值。

然後,你可以思考一下自己:這個函數何時會給出不同的值?那麼,只有當level獲得不同的值時纔會這樣做。這是什麼時候發生的?那麼,它只發生在構造函數中,所以,這意味着,它永遠不會再發生對象的生命......

+0

但我只希望每個對象具有一個readingLevel值。如果Level只在構造函數中獲得一個新值,那麼不會每次創建一個新對象時,構造函數都會被調用,並且一個新的readingLevel會得到一個新的數字。如果是這樣,它正在做我想做的事情。但是,每個對象對於readineLevel都會得到相同的結果。我錯過了什麼 – Aaron 2012-01-18 23:26:16

0

這是因爲您正在使用random.Next()和您的類的構造函數中的級別評估,請記住,只有在創建對象的新實例時才執行構造函數,因爲它會執行多次創建一個不同的方法,您可以在其中調用隨機和級別評估,這樣您每次都可以獲得不同的值或使用例如:

public bool Level() 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
    return level; 
} 
+0

'level'不能同時是一個字段和方法... – CodesInChaos 2012-01-18 23:13:48

+0

@CodeInChaos:但是,'level'和'Level'可以。在編輯之前,它讀作「public bool reading level()」,由於閱讀和關卡之間的拼寫錯誤而導致語法無效,更不用說命名字段和方法是相同的。 – 2012-01-18 23:28:03

0

請嘗試以下操作。將隨機等級的選擇移至readingLevel函數。

Random random = new Random(); 
public Student() 
{ 
} 

public bool readingLevel()//this always returns one value for the entire program. 
{ 
    int randomLevel=random.Next(1,3); 
    level = (randomLevel % 2 == 0); 
    return level; 
} 
3

它看起來就像你正在試圖獲得一個隨機數!
大眼夾

那麼你可以嘗試這樣的事:

static Random random = new Random(); 

public Student() 
{ 
    lock (random) 
    { 
     int randomLevel=random.Next(1,3); 
     level = (randomLevel % 2 == 0); 
    } 
} 
public bool readingLevel()//this always returns one value for the entire program. 
{ 
    return level; 
} 

與片斷的問題似乎是,你實例化一個新的Random類與每個類的實例。 這不是Random應該被使用的方式,而是應該使用Random類實例來獲取多個隨機數。

原因在於.Net中的隨機數使用基於狀態(種子)的僞隨機算法,每當你要求一個新的隨機數時該狀態就會改變。通過在相對較短的時間範圍內實例化多個隨機類,所有這些類都將以相同的種子啓動(基於系統時間),並且所有這些類都會給出相同的隨機數。

+0

同時用於調用Clippy的+1和-1。 (+1,因爲它很有趣; -1因爲它是......好吧,Clippy) – 2012-01-18 23:09:19

3

它看起來像你的隨機生成器是學生的實例變量。由於生成器使用當前時間作爲種子,如果您在短時間內創建了一羣學生,他們都將擁有一個具有相同種子和相同結果的生成器。你可以使隨機生成器成爲一個靜態變量,或者更好的是,使用構造函數注入並將該關卡傳遞給Student的構造函數。

class Student 
{ 
    private static Random random = new Random(); 

    public Student() 
    { 
    level = random.NextDouble() < 0.5; 
    } 

    public bool readingLevel() 
    { 
    return level; 
    } 
} 

或使用constructor injection所以你的學生班是確定性的。

class Student 
{ 
    private boolean level; 

    public Student(boolean readingLevel) 
    { 
    this.level = readingLevel; 
    } 
    public boolean readingLevel() 
    { 
    return level; 
    } 
} 
1

其他人也這麼說過,但我認爲這個觀點值得用一個例子來強調。

public class Student 
{ 
    Random random = new Random(); 

    public Student() 
    { 
     int randomLevel=random.Next(1,3); 
     level = (randomLevel % 2 == 0); 
    } 

    public bool readingLevel()//this always returns one value for the entire program. 
    { 
     return level; 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     var students = new List<Student>(); 
     for (int i = 0; i < 10; i++) 
      students.Add(new Student()); 

     //Now you have 10 Students; each Student has its own random number generator 
     //The generators were created within microseconds of each other, so they most likely have THE SAME SEED 
     //Because they have the same seed, they will generate identical sequences of numbers 
     //Each student's reading level is calculated from the first call to .Next(1, 3) on its own RNG. 
     //The RNGs have the same seed, so each will return the same value for the first call to .Next(1, 3) 
     //Therefore, all students will have the same reading level! 
    } 
}