【问题标题】:Random Array problems随机数组问题
【发布时间】:2013-06-26 14:37:30
【问题描述】:

我在这部分的代码中遇到了问题:

Random rand = new Random();
string[] MyRandomArray = choices.OrderBy(x => rnd.Next()).ToArray();
string[] newArray = new string[4];

int num = 0;

for (num = 0; num < 3; num++)
{
    newArray[num] = MyRandomArray[num];
}

newArray[num] = "1";

string[] finalArray = newArray.OrderBy(x => rnd.Next()).ToArray();
this.radioButton1.Text = newArray[0];
this.radioButton2.Text = newArray[1];
this.radioButton3.Text = newArray[2];
this.radioButton4.Text = newArray[3];

我要做的是在单选按钮 1、2、3 和 4 的 newArray 中获取不同的数组位置。但是,我在分配的最后一个数组中遇到了问题。它不包含在随机播放中,因此我得到的唯一随机值是单选按钮 1、2 和 3。每当我尝试重新启动程序时,单选按钮 4 保持不变。

【问题讨论】:

  • 将您的 for 循环更改为 for (num = 0; num &lt;= 3; num++) =)
  • 感谢 andre 的快速响应,我不能这样做,因为我想分配 newArray[num] = "1"
  • 但是,在那个时候,num 是 2。你永远不会为 newArray[3] 设置值!
  • 我将num赋值为0,然后将3个字符串传递给newArray,并将新数组的最后一个元素赋值给1
  • 再次重申:此时,num 为 2。您必须像 num+1 一样指定才能到达最后一个(第 4 个)元素。

标签: c# arrays random


【解决方案1】:

关于随机抽样和潜在问题的一句话:

Random Class 在生成唯一随机数序列的能力方面存在一些限制,请参阅文档的备注部分:

  1. 具体来说,因为 Random 的默认构造函数初始化 使用基于系统时钟的种子,您可以重复 随机实例的初始化重复时的序列 很快。前面引用的备注部分包括 演示此问题的代码。
  2. 不保证调用 Random 类实例的方法 是线程安全的。所以使用 Random 的单个实例来避免 种子问题可能会遇到其他线程问题。

使用Guid.NewGuid Method 对集合进行采样将为产生随机排序提供更好的结果,因为如果快速连续调用它不会重复序列。但是,它确实带有一些警告:

  1. 虽然它作为随机选择器在卡方检验中表现良好,但 它不适用于加密目的,也不是直接的 替代实际的随机数生成器。
  2. 只要 NewGuid 生成的 GUID 是版本 4 GUID, GUID 确实包含随机内容;然而,这可能 未来的变化。微软尚未发表任何声明 保证 GUID 将包含随机内容,只是它们将是 独一无二,碰撞概率极低。

下面是使用 NewGuid 的样子:

string[] myRandomArray = choices.OrderBy(x => Guid.NewGuid()).Take(3).ToArray();

使用RNGCryptoServiceProvider Class 是产生可靠随机抽样的最佳解决方案。它既是线程安全的,也不会受到 Random 类的种子问题的影响。但是,它确实需要更多的代码来实现。

// TODO: Add code to demonstrate using RNGCryptoServiceProvider

您可以使用 take 而不是 For 循环,因为您已经在使用 LINQ:

// Get 3 random choices in a List.
List<string> myChoices = choices.OrderBy(x => Guid.NewGuid()).Take(3).ToList();

// Add the correct answer.
myChoices.Add(theAnswer);

// Randomize the resulting set of 4 choices into an Array.
string[] myRandomizedChoices = myChoices.OrderBy(x => Guid.NewGuid()).ToArray();

this.radioButton1.Text = myRandomizedChoices[0];
this.radioButton2.Text = myRandomizedChoices[1];
this.radioButton3.Text = myRandomizedChoices[2];
this.radioButton4.Text = myRandomizedChoices[3];

【讨论】:

  • 我明白了,所以这段代码将从选择数组中取 4?我可以将它分配给另一个数组吗因为我只想取 3 而第 4 个元素将是一个分配字符串
  • 感谢您的帮助,看来我用 if else 和随机数解决了我的问题
  • @MaryGraceIsananViaje Guids are not random 不应用作随机数生成器。这段代码本质上是有缺陷的,不应该使用它,因为它不能被依赖于工作,即使它可能在某些情况下工作。
  • Random 对于实际目的来说已经足够好了——不是真正随机的,但对于非加密目的来说已经足够了。当您在每次迭代中创建 Random 类的新实例时,就会出现您所说的问题,但问题中没有发生这种情况。
  • @Servy 实际上,您不正确。仅仅因为 Guids 可以单调增加并不意味着它们会单调增加。您提供的链接专门讨论了版本 1 指南。由 .NET 中的 Guid.NewGuid() 和 SQL 中的 NEWID() 生成的 Guid 是版本 4 的 Guid,并且足够随机以对样本集进行排序。 SQL 中有一个使用NEWSEQUENTIALID() 函数的单调递增的 GUID,但仅限于列的默认值。
猜你喜欢
  • 2019-11-30
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多