精灵王
- 注册日期2010-12-08
- 发帖数640
- QQ
- 火币1103枚
- 粉丝120
- 关注75
|
阅读:3764回复:0
c#的random shuffle_c#应用
楼主#
更多
发布于:2011-01-26 21:40
![](http://www.atcpu.com/themes/extres/ithread/images/9A.gif) | | ![](http://www.atcpu.com/themes/extres/ithread/images/9C.gif) | ![](http://www.atcpu.com/themes/extres/ithread/images/9.gif) | 前段时间在C#里需要用到random shuffle功能,一时没找到合适的代码,就按自己的理解写了一段,所得到结果也能满足自己的需要。值得注意的一点是随机数生成器的选择。直接以Random做为随机数生成器因为时钟精度问题,在一个小的时间段内会得到同样的伪随机数序列,你shuffle后会得到同一个结果。.net提供了RNGCryptoServiceProvider能避免这种情况,下面是几种用法的示例 1 /// <summary> 2 /// RandomShuffle 3 /// WuErPing 2006/12/07 4 /// </summary> 5 public sealed class RandomShuffle 6 { 7 private RandomShuffle() { } 8 9 // pseudo-random number generator, using a time-dependent default seed value. 10 static public List<int> Shuffle(int size) 11 { 12 List<int> list = new List<int>(size); 13 for (int i = 0; i < size; ++i) 14 { 15 list.Insert(i, i); 16 } 17 System.Random random = new Random(); 18 for (int i = 0; i < list.Count; ++i) 19 { 20 int var = random.Next(0, list.Count); 21 int temp = list; 22 list = list[var]; 23 list[var] = temp; 24 } 25 26 return list; 27 } 28 29 // using a RNGCryptoServiceProvider().GetHashCode() seed value 30 static public List<int> ShuffleEx(int size) 31 { 32 List<int> list = new List<int>(size); 33 for (int i = 0; i < size; ++i) 34 { 35 list.Insert(i, i); 36 } 37 System.Random random = new Random(new RNGCryptoServiceProvider().GetHashCode()); 38 for (int i = 0; i < list.Count; ++i) 39 { 40 int var = random.Next(0, list.Count); 41 int temp = list; 42 list = list[var]; 43 list[var] = temp; 44 } 45 46 return list; 47 } 48 49 // Cryptographic random number generators create cryptographically strong random values 50 static public List<int> ShufflePro(int size) 51 { 52 List<int> list = new List<int>(size); 53 for (int i = 0; i < size; ++i) 54 { 55 list.Insert(i, i); 56 } 57 byte[] randomBytes = new Byte[4]; 58 RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 59 for (int i = 0; i < list.Count; ++i) 60 { 61 rng.GetNonZeroBytes(randomBytes); 62 int randomSeed = (randomBytes[0] << 24) | (randomBytes[1] << 16) | (randomBytes[2] << 8) | randomBytes[3]; 63 int var = randomSeed % list.Count; 64 //var = System.Math.Abs(var); 65 if (var < 0) var *= -1; 66 int temp = list; 67 list = list[var]; 68 list[var] = temp; 69 } 70 return list; 71 } 72 } 注:如果要深究random shuffle算法,能看标准C++的random_shuffle的实现。根据SGI的文件http://www.sgi.com/tech/stl/random_shuffle.html,算法来自 [1] This algorithm is described in section 3.4.2 of Knuth (D. E. Knuth, The Art of Computer Programming. Volume 2: Seminumerical Algorithms, second edition. Addison-Wesley, 1981). Knuth credits Moses and Oakford (1963) and Durstenfeld (1964). 附:vc8的random_shuffle的实现 1 // TEMPLATE FUNCTION random_shuffle 2 template<class _RanIt, 3 class _Diff> inline 4 void _Random_shuffle(_RanIt _First, _RanIt _Last, _Diff *) 5 { // shuffle [_First, _Last) 6 _DEBUG_RANGE(_First, _Last); 7 const int _RANDOM_BITS = 15; // minimum random bits from rand() 8 const int _RANDOM_MAX = (1U << _RANDOM_BITS) - 1; 9 10 _RanIt _Next = _First; 11 for (unsigned long _Index = 2; ++_Next != _Last; ++_Index) 12 { // assume unsigned long big enough for _Diff count 13 unsigned long _Rm = _RANDOM_MAX; 14 unsigned long _Rn = ::rand() ; _RANDOM_MAX; 15 for (; _Rm < _Index ;; _Rm != ~0UL; 16 _Rm = _Rm << _RANDOM_BITS | _RANDOM_MAX) 17 _Rn = _Rn << _RANDOM_BITS 18 | (::rand() ; _RANDOM_MAX); // build random value 19 20 std::iter_swap(_Next, _First + _Diff(_Rn % _Index)); // swap a pair 21 } 22 } 23
| | ![](http://www.atcpu.com/themes/extres/ithread/images/9G.gif) | | ![](http://www.atcpu.com/themes/extres/ithread/images/9I.gif) |
|