8

这是一位面试官提出的问题。我无法回答。

问题是,假设您想从给定数组中选择一个随机数。

条件是您不应该按顺序选择任何东西,也不应该使用内置的 Random 函数。

我不知道。想知道这个 Math.Random 对我们有什么作用?

我用谷歌搜索并没有找到其背后的实现/逻辑。

有谁知道吗?

4

8 回答 8

22

到目前为止,三个人已经告诉你使用最后一位数字。这行不通。尝试在一个紧密的循环中这样做,您很快就会明白为什么这是一个坏主意。

这个问题不是很好提出的。我喜欢在面试中提出模棱两可的问题,因为你可以了解候选人如何处理模棱两可的情况。在这种情况下,我会立即反击并找出面试官所说的“随机”是什么意思。伪随机性是否足够好?是否有可用的高质量熵源?

一旦你有一个明确的问题,它应该更容易回答。

问题归结为管理熵。如果你有一个非常弱的熵源——比如 Ticks 的值(不是最后一个数字,它毫无价值,而是整个值),那么你可以使用它来播种伪随机数生成器。如果您有高质量的熵源,那么您可以直接使用它来生成随机位。

于 2013-03-21T15:47:28.530 回答
7

保证随机。(舌头紧贴脸颊):

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);
    }
}
于 2013-03-21T16:10:40.483 回答
5

如果您只想从数组中获取一项Random,而不使用类,则可以使用modulo具有未知值的函数,例如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]);
于 2013-03-21T15:35:41.673 回答
4

我会用

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();
        }
    }
于 2013-03-21T15:34:34.223 回答
1

这是 C 中随机数的实现。您可以尝试用 C# 重写它。

C 的随机数:终于结束了? http://www.cse.yorku.ca/~oz/marsaglia-rng.html

它似乎质量非常高。

但是在面试中编写这段代码并不容易,但你绝对可以告诉他使用的想法。

于 2013-03-21T15:37:28.737 回答
0

只是一个想法,您可以使用最后一位数字DateTime.Now.Ticks来获得选择索引的基础。或者也许是同一件事上的一些哈希函数。或者使用可以为您提供从辐射测量的随机数的网络服务。Math.Random只是从预定义的表中挑选(是的,它确实不是随机的)。

于 2013-03-21T15:35:17.270 回答
0

首先,它被称为伪随机而不仅仅是随机,因为随机序列不可能以计算形式生成,

大多数伪随机数生成器 PRNG 都采用这种形式:

在时间 0:R(0) = 随机(种子)

在时间 i:R(i) = Random(R(i-1));

其次,随机并不意味着您不知道第 i 个结果会是什么,而是该系列是稳健的,并且很难猜测给定结果链的公式或种子

希望这可以帮助

于 2013-03-21T16:12:54.163 回答
0

我想他们只是想看看你是否了解LCG(线性同余生成器)算法。

然而,他们背后的数学有点棘手,所以我怀疑他们是否能指望你能在脑海中写下一个。

但是如果做不到这一点,你就不能像这样作弊来生成一个随机索引吗?

int index = Guid.NewGuid().GetHashCode() % array.Length;

于 2013-03-21T15:39:37.897 回答