2013-01-23 140 views
15

我搜索了一段時間,一直在努力尋找這個,我試圖生成幾個隨機的,唯一的數字是C#。我使用System.Random,和我使用的是datetime.now.ticks種子:生成隨機,唯一的值C#

public Random a = new Random(DateTime.Now.Ticks.GetHashCode()); 
private void NewNumber() 
    { 
    MyNumber = a.Next(0, 10); 
    } 

我打電話NewNumber(定期),但問題是我經常收到重複的數字。有人建議,因爲我每次做這件事都是隨機的,它不會產生一個隨機數,所以我把聲明放在我的函數之外。任何建議或比使用System.Random更好的方法?謝謝

+2

http://csharpindepth.com/Articles/Chapter12/Random.aspx – Habib

+0

只要你只是創建Random對象一次,你不應該有問題。如果你想要的數字是唯一的(還沒有這個數字),那麼你需要添加額外的,而不僅僅是使用隨機 – RoneRackal

+1

你在尋找「數字1..10排列」而不是「隨機數在範圍1..10「? (Definiitely給你隨機序列10個唯一的數字) –

回答

14

我打電話NewNumber()定期,但問題是我經常得到 重複的數字。

Random.Next不保證數字是唯一的。你的範圍是從0到10,你可能會得到重複的值。可能是你可以設置一個int的列表,並在檢查它是否包含重複之後在列表中插入隨機數。例如:

public Random a = new Random(); // replace from new Random(DateTime.Now.Ticks.GetHashCode()); 
           // Since similar code is done in default constructor internally 
public List<int> randomList = new List<int>(); 
int MyNumber = 0; 
private void NewNumber() 
{ 
    MyNumber = a.Next(0, 10); 
    if (!randomList.Contains(MyNumber)) 
     randomList.Add(MyNumber); 
} 
+2

+1。對於任何超過10個列表的選擇都不好,HashSet會更好。並且不需要按照這種方式初始化隨機數 - 在默認的構造函數中完成類似的代碼... –

+0

感謝堆完美運行! –

13

如果範圍僅爲0到9,您可以嘗試對可能的整數進行混洗。這增加了避免編號生成中的任何衝突的好處。

var nums = Enumerable.Range(0, 10).ToArray(); 
var rnd = new Random(); 

// Shuffle the array 
for (int i = 0;i < nums.Length;++i) 
{ 
    int randomIndex = rnd.Next(nums.Length); 
    int temp = nums[randomIndex]; 
    nums[randomIndex] = nums[i]; 
    nums[i] = temp; 
} 

// Now your array is randomized and you can simply print them in order 
for (int i = 0;i < nums.Length;++i) 
    Console.WriteLine(nums[i]); 
+0

我剛剛測試了一個,它運行得很好!非常感謝! –

+0

小心!這是一個不正確的洗牌實施!我會立即發佈一個正確的實施。 –

+0

(現在編輯我的評論太晚了)。請在下面查看我的帖子以獲取正確的實施,以及關於它的一些討論的鏈接。 –

1

取決於你是什麼真的是你可以做這樣的事情後:

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace SO14473321 
{ 
    class Program 
    { 
     static void Main() 
     { 
      UniqueRandom u = new UniqueRandom(Enumerable.Range(1,10)); 
      for (int i = 0; i < 10; i++) 
      { 
       Console.Write("{0} ",u.Next()); 
      } 
     } 
    } 

    class UniqueRandom 
    { 
     private readonly List<int> _currentList; 
     private readonly Random _random = new Random(); 

     public UniqueRandom(IEnumerable<int> seed) 
     { 
      _currentList = new List<int>(seed); 
     } 

     public int Next() 
     { 
      if (_currentList.Count == 0) 
      { 
       throw new ApplicationException("No more numbers"); 
      } 

      int i = _random.Next(_currentList.Count); 
      int result = _currentList[i]; 
      _currentList.RemoveAt(i); 
      return result; 
     } 
    } 
} 
8

我張貼正確執行洗牌的算法,因爲另一張貼在這裏不生產一個統一的洗牌。

正如其他答案所述,對於少量要隨機化的值,您可以簡單地使用這些值填充數組,然後使用數組,然後使用所需的許多值。

以下是Fisher-Yates Shuffle(又名Knuth Shuffle)的實現。 (閱讀該鏈接的「實現錯誤」部分(搜索「總是從每次迭代中的整個有效數組索引中選擇j」),以查看關於此處發佈的其他實現的錯誤的一些討論。)

using System; 
using System.Collections.Generic; 

namespace ConsoleApplication2 
{ 
    static class Program 
    { 
     static void Main(string[] args) 
     { 
      Shuffler shuffler = new Shuffler(); 
      List<int> list = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
      shuffler.Shuffle(list); 

      foreach (int value in list) 
      { 
       Console.WriteLine(value); 
      } 
     } 
    } 

    /// <summary>Used to shuffle collections.</summary> 

    public class Shuffler 
    { 
     /// <summary>Creates the shuffler with a <see cref="MersenneTwister"/> as the random number generator.</summary> 

     public Shuffler() 
     { 
      _rng = new Random(); 
     } 

     /// <summary>Shuffles the specified array.</summary> 
     /// <typeparam name="T">The type of the array elements.</typeparam> 
     /// <param name="array">The array to shuffle.</param> 

     public void Shuffle<T>(IList<T> array) 
     { 
      for (int n = array.Count; n > 1;) 
      { 
       int k = _rng.Next(n); 
       --n; 
       T temp = array[n]; 
       array[n] = array[k]; 
       array[k] = temp; 
      } 
     } 

     private System.Random _rng; 
    } 
} 
+0

@downvoters:你是否在調查其他隨機洗牌問題?有問題的答案是接受答案之下的答案。它使用了不正確的隨機播放算法。另請參閱我對該答案的評論。 –

+0

爲什麼這比另一個好? (apar從你說它通用) –

+0

@Mitulátbáti你的意思是「其他」的答案?如果你的意思是「接受的答案」,那麼這一個更好,因爲它具有複雜性'O(N)',而接受的答案具有複雜性'O(N^2)'。 –

-1

你也可以使用一個DataTable存儲每個隨機值,然後簡單地執行而隨機方法!=值在DataColumn的

8

注意,我不建議這樣:)。 這裏有一個 「oneliner」 以及:

//This code generates numbers between 1 - 100 and then takes 10 of them. 
var result = Enumerable.Range(1,101).OrderBy(g => Guid.NewGuid()).Take(10).ToArray(); 
+0

就像你去過的地方。但是爲什麼不呢:'Enumerable.Range(0,9).OrderBy(g => rand.NextDouble())。ToList()'然後你得到範圍作爲每個問題。 – SDK

+1

如果你想要兩個唯一的數字在1和10,000,000之間,這將會非常緩慢。 – Rob

-3

試試這個:

private void NewNumber() 
    { 
    Random a = new Random(Guid.newGuid().GetHashCode()); 
    MyNumber = a.Next(0, 10); 
    } 

一些Explnations:

Guidbase on here:表示一個全局唯一標識符(GUID)

Guid.newGuid()產生一個唯一的標識符,如"936DA01F-9ABD-4d9d-80C7-02AF85C822A8"

,這將是唯一在全宇宙base on here

哈希碼here從我們的唯一標識符生成一個唯一的整數

所以Guid.newGuid().GetHashCode()爲我們提供了一個唯一的編號和隨機類將產生真正的隨機數扔這

+3

請添加說明。 – OhBeWise

+0

@Rob是的,這會產生一個獨特的價值,你測試了嗎? – AliTheOne

+3

不,它不會。沒有任何理由,連續兩次調用都不會產生相同的值。爲每個樣品重新播種是一種經典的反模式。 –

0

而在這裏我的版本發現N隨機唯一編號使用HashSet。 看起來很簡單,因爲HashSet只能包含不同的項目。 這很有趣 - 使用List或Shuffler會更快嗎?

using System; 
using System.Collections.Generic; 

namespace ConsoleApplication1 
{ 
    class RnDHash 
    { 
     static void Main() 
     { 
      HashSet<int> rndIndexes = new HashSet<int>(); 
      Random rng = new Random(); 
      int maxNumber; 
      Console.Write("Please input Max number: "); 
      maxNumber = int.Parse(Console.ReadLine()); 
      int iter = 0; 
      while (rndIndexes.Count != maxNumber) 
      { 
       int index = rng.Next(maxNumber); 
       rndIndexes.Add(index); 
       iter++; 
      } 
      Console.WriteLine("Random numbers were found in {0} iterations: ", iter); 
      foreach (int num in rndIndexes) 
      { 
       Console.WriteLine(num); 
      } 
      Console.ReadKey(); 
     } 
    } 
} 
-2

您可以使用C#

Random ran = new Random(); 
int randomno = ran.Next(0,100); 

基本隨機函數,你現在可以使用值在randomno你想要什麼,但請記住,這將產生0100之間的隨機數只有你可以擴展到任何數字。

+0

這沒有給予獨特價值的受讓人。 –

0

請檢查此準備好使用的方法:在範圍內給出&您想獲得的號碼的數量。

public static int[] getUniqueRandomArray(int min, int max, int count) { 
    int[] result = new int[count]; 
    List<int> numbersInOrder = new List<int>(); 
    for (var x = min; x < max; x++) { 
     numbersInOrder.Add(x); 
    } 
    for (var x = 0; x < count; x++) { 
     var randomIndex = Random.Range(0, numbersInOrder.Count); 
     result[x] = numbersInOrder[randomIndex]; 
     numbersInOrder.RemoveAt(randomIndex); 
    } 

    return result; 
}