【问题标题】:Unique number in random?随机的唯一编号?
【发布时间】:2012-03-07 06:40:46
【问题描述】:

我知道网上有很多关于它的问题,但我想知道为什么我的方法失败了 我做错了什么?

public class Generator
{

    private static readonly Random random = new Random();

    private static readonly object SyncLock = new object();

    public static int GetRandomNumber(int min, int max)
    {
        lock (SyncLock)
        { 
            return random.Next(min, max);
        }
    }

}


[TestFixture]
public class Class1
{
    [Test]
    public void SimpleTest()
    {

        var numbers=new List<int>();
        for (int i = 1; i < 10000; i++)
        {
            var random = Generator.GetRandomNumber(1,10000);
            numbers.Add(random);
        }

        CollectionAssert.AllItemsAreUnique(numbers);

    }
}

编辑 测试方法失败!!抱歉没提

感谢您的宝贵时间和建议

【问题讨论】:

  • @Boo 当你的评论弹出时我很害怕......:O
  • 最近大量不小心提出的问题涌入。
  • 您是否正在寻找某种随机重新分配数字 1-10000 的洗牌算法?
  • @TimSchmelter:什么?他发布了代码并说基本上“它不起作用”。正是那些不厌其烦地解释和回答“问题”的人的真棒才使答案如此出色。它与这个问题的质量无关。
  • @TimSchmelter:OP 声称“该方法失败”,但未指定哪种方法以及以何种方式失败。如果他们说测试失败或断言被触发或准确描述失败的东西,那么我会同意你的看法。但是除了“方法”之外没有对失败的描述,其中我计算了 OP 拥有的两个和他们不拥有的 6 个 - 其中任何一个都可能是“失败”。

标签: c#


【解决方案1】:

除非您非常幸运,否则您怎么可能期望来自一组 10,000 个可能值的 10,000 个随机数序列都是唯一的?你的期望是错误的。

掷硬币两次。你真的认为 TH 和 HT 是唯一可能的序列吗?

是什么让您认为随机数的工作方式应该有所不同?

随机数生成器的输出是可能的:

1, 1, 1, 1, 1, 1, ..., 1

是这样的:

1, 2, 3, 4, 5, 6, ..., 10000

事实上,这两个序列的可能性相同!

【讨论】:

  • 1..10000 行包含 10k 个唯一数字。为什么不可能?
  • 我说“除非你非常幸运。”
  • @zerkms - 同意。不是不可能。但是你可以相当自信,如果你在整个宇宙的生命周期内每秒运行一次这个程序,你永远不会得到一个没有重复的集合。这是生日问题的一个变体:en.wikipedia.org/wiki/Birthday_problem
  • @perfectist, Jason:哎呀,我错过了“除非你非常幸运”部分
  • @Jason 。你说得对,我不能详细介绍项目的所有细节,但我需要生成 1 到 10000 之间的唯一数字。
【解决方案2】:

您似乎误解了Random 类生成了一个唯一 序列,尽管显然是随机数。这根本不是那么回事;随机性意味着下一个数字可能是任何可能的选择,而不仅仅是任何除了我以前见过的

既然如此,您的测试失败也就不足为奇了:10000 个随机生成的整数(不少于 1 到 10000 之间)是唯一的概率微乎其微。

【讨论】:

    【解决方案3】:

    随机!=唯一

    这里的重点是,您的代码应该为您的问题建模,而您的实际上没有。随机不等于唯一。如果您想要唯一,您需要获取一组值并将它们随机排列。

    如果你真的想要随机数,你不能指望它们是唯一的。如果您的 (P)RNG 提供均匀分布,那么经过 许多 次试验,您应该会看到每个值的相似计数(请参阅 Law of Large Numbers)。案例可能会出现看起来“错误”的情况,但您不能忽视您碰巧遇到的情况。

    【讨论】:

    • -1 N 个唯一数字可以在 O(n) 中生成。 OrderBy 将在 O(n*log(n)) en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle 中运行
    • Guids 保证是唯一的,但不能保证它们产生的值足以对序列进行洗牌。如果是您想要的洗牌,请使用洗牌算法。
    • 讽刺的是,您的回答违反了您第一句话中所述的原则。杰森是正确的。 Guid 是唯一性的来源,而不是随机性的来源。无法保证您不会得到一万个已按顺序排序的 guid;事实上,有一些版本的 guid 生成算法正是这样做的。
    【解决方案4】:
    public static void FisherYatesShuffle<T>(T[] array)
    {
        Random r = new Random();
        for (int i = array.Length - 1; i > 0; i--)
        {
            int j = r.Next(0, i + 1);
            T temp = array[j];
            array[j] = array[i];
            array[i] = temp;
        }
    }
    
    int[] array = new int[10000];
    
    for (int i = 0; i < array.Length; i++) array[i] = i;
    FisherYatesShuffle(array);
    

    【讨论】:

    • @user231465 只是能够洗牌任何类型的数组,而不仅仅是整数数组
    【解决方案5】:

    我认为你没有提到你的 test 方法失败了。

    它失败了,因为您的随机生成器没有生成唯一数字。我不知道在目前的情况下它会如何。

    【讨论】:

    • 是的,测试失败了,我希望它通过以证明我可以唯一地生成随机数
    • 那么你需要更新你的代码来产生这个结果。就目前而言,测试失败是正确的结果。
    • 好的。我想更新代码以产生结果,但我似乎找不到如何?
    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    相关资源
    最近更新 更多