【发布时间】:2010-12-08 12:10:55
【问题描述】:
我知道 C# 有 Random 类,并且可能在 LINQ 中有几个类可以做到这一点,但是如果我要编写自己的代码来从集合中随机选择一个项目而不使用任何内置的 .NET 对象,如何会这样吗?
我似乎无法确定此操作所需的逻辑 - 我如何告诉系统何时停止迭代并随机选择当前值?
编辑:这是一个假设性问题。这与生产编码问题无关。我只是好奇。
【问题讨论】:
我知道 C# 有 Random 类,并且可能在 LINQ 中有几个类可以做到这一点,但是如果我要编写自己的代码来从集合中随机选择一个项目而不使用任何内置的 .NET 对象,如何会这样吗?
我似乎无法确定此操作所需的逻辑 - 我如何告诉系统何时停止迭代并随机选择当前值?
编辑:这是一个假设性问题。这与生产编码问题无关。我只是好奇。
【问题讨论】:
从集合中选择一个随机元素可以如下完成。
Random r = new Random();
int randomIndex = r.Next(0, myCollection.Size -1);
var randomCollectionItem = myCollection[randomIndex];
除非你有很好的理由,否则没有必要编写自己的随机生成器。
【讨论】:
我对你的建议是不要这样做。不管你认为你不想使用内置库的原因是什么,我很确定你误解了一些东西。请回到绘图板。
以上所有建议在技术上都是准确的,但有点像给想要提炼自己的油以用于汽车的人提供一本化学教科书。
【讨论】:
有很多pseudo-random number generators。它们并不是真正随机的,但它们具有不同的质量,由它们的统计和顺序属性以及它们适用的目的来区分。
这在很大程度上取决于“您需要它的随机性”。如果它只需要“在人类看来是随机的”,那么简单的生成器看起来像这样:
rnd = seed; // some starting value
rnd = (a * rnd + b) % c; // next value
...
对于选择好的 a、b 和 c 值,这些生成器适用于简单的统计测试。这些you find here的详细讨论和共同价值观。
一种有趣的方法是收集尽可能多的“外部”数据(例如按键之间的时间、鼠标移动、磁盘读取的持续时间等),并使用一种在丢弃依赖性的同时累积随机性的算法。不过,这在数学上很棘手(不久前,IIRC 出现了一次关键攻击,基于其中一个并不像想象的那样随机)。
只有极少数特殊应用使用真正随机的外部硬件源 - 介于开放输入放大器和放射性衰变之间的任何东西。
【讨论】:
您需要使用种子,这是计算机本身提供的半随机的东西。 也许使用非常精细的解析时间并在调用该方法时使用最后几微秒。这应该足够随机生成从 00 到 99 的任何内容,然后您可以从那里开始。
【讨论】:
听起来您的问题不在于计算随机数,而在于如何使用该随机数从列表中选择一个项目。假设您可以通过某种方式创建一个随机数,您所需要做的就是将它用作列表索引器的参数。
int index = customRandomGenerator.Next();
var selection = items[index];
假设您关于必须遍历列表的假设是正确的(或者该集合没有索引器),那么您可以这样做:
int index = customRandomGenerator.Next();
Item selection = null;
for (int i = 0; i < items.Length; i++)
{
if (i == index)
{
selection = items[i];
break;
}
}
【讨论】:
.Net 框架中唯一真正的“加密强”随机数生成器在 System.Cryptography.RandomNumberGenerator 中 - 通过 Reflector 运行它以查看它的作用?查看您的问题,您需要知道集合的计数,否则您可能永远无法检索项目-您需要指定开始和结束值以从中提取随机数-随机类效果最好-通过反射器弹出它.
【讨论】:
好吧,我从来没有想过自己实现它,因为这似乎是在重新发明轮子,但你可以看看这篇维基百科文章,希望它能帮助你做你想做的事
【讨论】: