Math.Random算法

Bil*_*lla 8 c c# c++ java algorithm

这是一位采访者提出的问题.我无法回答.

问题是,假设你想从给定的数组中选择一个随机数.

条件是你不应该在顺序中选择任何东西而不是使用内置的随机函数.

我不知道.想知道这个Math.Random对我们有什么影响吗?

我用Google搜索并没有找到背后的实现/逻辑.

谁知道?

Eri*_*ert 22

到目前为止,有三个人告诉过你使用Ticks的最后一位数字.这不起作用.尝试在紧密循环中这样做,你很快就会明白为什么这是一个坏主意.

问题不是很好.我喜欢在面试中提出含糊不清的问题,因为你可以找出候选人如何处理一个模棱两可的情况.在这种情况下,我会立即回过头来,通过"随机"找出面试官的意思.伪随机性是否足够好?是否有高质量熵的来源?

一旦你有一个澄清的问题,它应该更容易回答.

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

  • @ ken2k:你已经在你的推理中指出了谬论."我们不知道这将返回什么"和"我们知道返回的值是可靠的随机分布"是**对立**,但你将它们视为**同义词**.我们不能轻易地假设任何未知数量是随机分布的!它可能是高度非随机的.**我们不知道**,因此我们不应该假设分配恰好是我们想要的. (5认同)
  • @Thomas:不,你的算法很糟糕.尝试连续十次运行程序,看看你得到了什么.我得到:6,37,95,81,68,69,50,12,5,3,36 - 6,4,95,81,2,55,0,68,58,99 - 6,37,95,81 ,68,12,50,79,58,90 ......注意到什么奇怪的?第一个数字总是六个,第二个数字通常是37个,第三个数字总是94个,第四个数字总是81个...这是*非常糟糕的随机性*. (3认同)
  • @Thomas:连续十次尝试. (3认同)
  • @ ken2k:我们必须区分外行人对"随机"的定义,这基本上是"我不知道的东西",以及工程师对随机的定义,这是一个*固有的不可预测的*过程,它产生的结果仍然可靠*将汇总*符合特定分布.一旦价值变得不可预测是不够的; 它的*分布必须符合某个模型*,因为它实际上是随机的. (2认同)

Jer*_*all 7

保证是随机的.(舌头FIRMLY在脸颊):

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @HighCore 现在,现在......唯一的要求是`条件是你不应该按顺序选择任何东西,也不应该使用内置的随机函数。` - 这通过了!:) (2认同)

ken*_*n2k 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]);
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 4

我会用

DateTime.Now.Tick 
Run Code Online (Sandbox Code Playgroud)

然后取足够的数字,例如 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

请参阅以下测试:

    [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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 这个算法很糟糕;多次运行时会产生高度非随机的结果。Ticks 对于生成随机数来说**不**完美。与处理器速度相比,它“不”经常发生变化,即使发生变化,程序执行的工作量和滴答数发生变化之间也存在很强的相关性。它根本不是“随机”的;它*与程序的行为紧密相关*。正如你所期望的那样;这是*为节目计时*。 (5认同)