构建一个非连续的数字列表(从大范围)

时间:2009-12-10 15:02:46

标签: c# .net asp.net sql sql-server

我需要创建一个符合范围的非连续数字列表。例如,我需要生成一个1到1百万的数字列表,并确保数字中的非数字按顺序排列,它们是完全混洗的。我想我的第一个问题是,是否有任何好的算法可以帮助以及如何最好地实现它。

我目前不确定实现的最佳方式,可以通过ac#console app吐出XML文件中的数字,也可以将数据吐出到表或一组表中,但是这实际上是制定“改组”数字集的最佳方法的第二步。

任何建议人员?

罗布

7 个答案:

答案 0 :(得分:3)

首先,如果 none 的数字按顺序排列,那么序列中的每个数字必须小于其前身。具有该属性的序列从最大到最小排序!显然这不是你想要的。 (或者你可能只是不想要5,7,7表格的任何后续序列?但是6,8,20会没问题?)

要正确回答您的问题,我们需要了解有关问题空间的更多信息。我想知道的事情:

1)范围的大小是否等于,大于或小于序列的大小?也就是说,你要问1到10之间的10个数字,1到10之间的5个数字或1到10之间的50个数字吗?

2)序列是否可以包含重复项? (如果序列中的项目数大于范围,则显然是。)

3)用于什么是随机性?大多数随机数生成器只是伪随机数;一个聪明的攻击者可以通过了解前一个“随机”数来推断出它。例如,如果您正在制作一系列五张牌来制作扑克牌,那么您需要非常强大的随机性;你不希望玩家能够推断出他们手中的对手。

答案 1 :(得分:2)

你想要“非顺序”怎么样?

您可以使用Random类轻松生成一个范围内的随机数列表:

Random rnd1 = new Random();
List<int> largeList = new List<int>();

for (int i = 0, i < largeNumber, i++)
{
  largeList.Add(rnd1.Next(1, 1000001);
}

编辑以添加

不可否认,Durstenfeld算法(显然是现代版的Fisher-Yates shuffle)要快得多:

var fisherYates = new List<int>(upperBound);
for (int i = 0; i < upperBound; i++)
{
  fisherYates.Add(i);
}

int n = upperBound;

while (n > 1)
{
   n--;
   int k = rnd.Next(n + 1);
   int temp = fisherYates[k];
   fisherYates[k] = fisherYates[n];
   fisherYates[n] = temp;
}

对于1到10000的范围,执行蛮力“找到一个我还没有使用的随机数”需要大约4-5秒,而这需要大约0.001。

支持Greg Hewgill获取链接。

答案 2 :(得分:2)

据我所知,你想获得一个随机数组的lenth 1mio,所有数字从1到1mio。没有重复,是吗?

你应该建立一个数字,其数字范围从1到1mio。然后开始洗牌。但它可能发生(即真正的随机性)两个甚至更多的数字是连续的。

看看here

答案 3 :(得分:1)

这是一个让你入门的C#功能:

public IEnumerable<int> GetRandomSequence(int max)
{
    var r = new Random();
    while (true)
    {
       yield return r.GetNext(max);
    }
}

这样称它可以得到一百万个数字,范围是0-9999999:

var numbers = GetRandomSequence(9999999).Take(1000000);

至于排序,或者如果您不想允许重复,请查看Enumerable.GetRange()(它将为您提供连续排序的序列)并使用Fisher-Yates(或Knuth)shuffle算法(你可以找到它的所有地方)。

答案 4 :(得分:0)

“完全洗牌”是一个非常被误解的术语。欺诈专家在检查什么应该是“随机”数据时使用的一个技巧是监视没有重复值的情况(如3743 *** 88 *** 123,因为在一个真正随机的序列中没有这样一对的机会非常低......究竟你想要做什么?究竟是什么意思“完全洗牌”?如果你的意思是随机的数字序列,那么只需使用CLR中的Random类。生成0到1M之间的随机数......尽可能多的......

答案 5 :(得分:0)

嗯,你可以选择这样的东西(假设你想要每个数字一次):

DECLARE @intFrom int
DECLARE @intTo int
DECLARE @tblList table (_id uniqueidentifier, _number int)

SET @intFrom = 0
SET @intTo = 1000000

WHILE (@intFrom < @intTo)
BEGIN
    INSERT INTO  @tblList
    SELECT       NewID(), @intFrom

    SET @intFrom = @intFrom + 1
END

SELECT    *  
FROM      @tblList
ORDER BY  _id

免责声明:我没有对此进行测试,因为我目前没有SQL Server。

答案 6 :(得分:0)

这可以满足您的需求:

1)按顺序填充数字列表。如果您的范围是1 - x,它将如下所示: [1,2,4,5,6,7,8,9,...,x]

2)在列表上循环x次,每次选择0到列表长度的随机数 - 1。

3)使用此选择的数字从列表中选择相应的元素,并将此数字添加到输出列表中。

4)删除刚从列表中选择的元素。冲洗,重复。

这适用于任何数字范围,而不仅仅是以1或0开头的列表。伪代码如下所示:

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
shuffled_nums = []
for i in range(0, len(nums)):
    random_index = rand(0,len(nums))
    shuffled_nums.add(nums[random_index])
    del(nums[random_index])