问题是,假设你想从给定的数组中选择一个随机数。 条件是不能按顺序选择任何内容并且不使用内置的Random函数。 我不知道。想知道这个Math.Random是如何为我们工作的?
我谷歌搜索了一下,并没有找到背后的实现/逻辑。
有人知道吗?
到目前为止,已经有三个人告诉你要使用Ticks的最后一位数字来生成随机数。 这种方法是行不通的。 如果在紧密循环中这样做,你很快就会明白为什么这是一个坏主意。
这个问题没有被很好地提出。我喜欢在面试中问模糊的问题,因为这样可以了解候选人如何处理模糊情况。在这种情况下,我会立即反击并找出面试官所说的“随机”是什么意思。伪随机性是否足够好?是否有高质量的熵源可用?
一旦你澄清了问题,回答就应该更容易了。
问题归结为管理熵。如果你有一个非常弱的熵源——比如Ticks的值(不是最后一位数字,它毫无价值,而是整个值),那么你可以使用它来种子化一个伪随机数生成器。如果你有一个高质量的熵源,那么你可以直接使用它来生成随机比特。
保证是随机的。(开玩笑):
void Main()
{
Enumerable.Range(0, 10).Select(x => ComeOnItsKindaRandom(0, 10)).Dump();
}
public int ComeOnItsKindaRandom(int minValue, int maxValue)
{
var query = "http://www.random.org/integers/?num=1&min={0}&max={1}&col=1&base=10&format=plain&rnd=new";
var request = WebRequest.Create(string.Format(query, minValue, maxValue));
var response = request.GetResponse();
using(var sr = new StreamReader(response.GetResponseStream()))
{
var body = sr.ReadToEnd().Trim();
return int.Parse(body);
}
}
如果您只想从数组中获取一个项,而不使用Random
类,则可以使用带有未知值的模数
函数,例如DateTime.Now.Ticks
:
string[] items = new[] { "1", "2", "3", "4", "5" };
// Modulo items.Lenth returns a value from 0 to Length - 1
int index = (int)(DateTime.Now.Ticks % items.Length);
Console.WriteLine(items[index]);
0
结尾,因此它经常可以被 2、5 和 10 整除。这几乎肯定会有利于根据数组长度返回相同的元素。编辑:在我的测试中,数组长度为 5 的索引始终返回 0
,数组长度为 6 的索引始终选择 0
或 2
。 - Chris SinclairDateTime.Now.Ticks
值进行更多微调,而不仅仅是直接按原样模数(例如,请参见Thomas的答案)。 - Chris SinclairI would use the
DateTime.Now.Tick
例如,对于Math.Random(10),我只取最后两个数字。
或者你可以像下面这样取此刻的模数:
public static class MyMath
{
private static int counter = 1;
public static int Random(int max)
{
counter++;
long ticks = DateTime.Now.Ticks;
int result = Math.Abs((int) (ticks/counter)%max);
return result;
}
}
请看以下测试:
[Test]
public void test()
{
List<int> test = new List<int>();
for (int i = 0; i < 10; i++)
{
test.Add(MyMath.Random(100));
}
Console.WriteLine("result:");
foreach (int i in test)
{
Console.WriteLine();
}
}
这是一个用C语言实现的随机数示例。你可以尝试用C#重写它。
C语言的随机数:终于结束了? http://www.cse.yorku.ca/~oz/marsaglia-rng.html
它似乎质量非常高。
但在面试中编写此代码可能并不容易,但你肯定可以告诉他使用的思路。
只是一个想法,你可以使用 DateTime.Now.Ticks
中的最后一位数字来选择索引的基础。或者对相同的东西进行一些哈希函数。或者使用一个可以提供从辐射中测量出的随机数的 Web 服务。 Math.Random
只是从预定义的表中选择(确实如此,它并不是真正的随机)。
我认为他们只是想知道你是否了解LCG(线性同余生成器)算法。
然而,它们背后的数学有些棘手,所以我怀疑他们不可能期望你能够脱口而出写一个。
但如果失败了,你难道不能像这样欺骗来生成一个随机索引吗?
int index = Guid.NewGuid().GetHashCode() % array.Length;
首先,伪随机数不仅仅是随机数,因为在计算形式下无法生成随机数序列,
大多数伪随机数生成器 PRNG 都采用以下形式:
在时间 0:R(0) = Random(Seed)
在时间 i:R(i) = Random(R(i-1));
其次,随机并不意味着您不知道第 i 次结果会是什么,而是该序列是强大的,并且很难猜测给定一系列结果的公式或种子
希望这有所帮助
Chat
。也请利用那个平台 :) - Billa