使用c#如何快速生成100万个不重复随机数

zxrliuyan 2016-08-18 08:27:37
如题,各位有没有遇到过类似需求?快速生成百万随机数?
...全文
2579 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
不重复的数字本身就不符合随机数的概念,你需要的是一个随机洗牌,洗牌楼上已经给出来了,你如果再需要一些随机性,请在洗牌前获取一下随机数然后用随机数确定洗牌数范围,然后洗牌。
白衣如花 2017-11-22
  • 打赏
  • 举报
回复
随机数本就是可以重复的,不能重复就不叫随机数了 你必须维护已生成的数,丢弃重复的。 或者直接从100W个数里面随机取,取出来的就移除掉,但这样就不符合你“随机数”的概念了
qq_41138974 2017-11-22
  • 打赏
  • 举报
回复 1
//取100个0到99之间的不重复的随机数 int [] nums = new int[100];//创建数组 for (int i = 0; i < 100; i++) { nums[i] = i;//给数组赋值 } Random random = new Random();//创建实例 for (int j = 0; j < 100; j++) { int id = random.Next(0, 100);//生成随机数 int temp = nums[j];// nums[j] = nums[id];// nums[id] = temp;//交换nums[]数组中两个元素的值 } for (int i = 0; i < 100; i++) { Console.WriteLine(nums[i]); }
xiaha3 2016-08-24
  • 打赏
  • 举报
回复
是不是打乱的1到100万就行?
xiaha3 2016-08-24
  • 打赏
  • 举报
回复
这个应用的用处不太好理解,最好把用处说清楚,看能否改进下
wanghui0380 2016-08-23
  • 打赏
  • 举报
回复
1.确认精度 2.MT随机数算法 3.hash表存储 实际上如果使用MT随机数算法,100w次内几乎可以说没有重复的数据,当然为了保险,你可以hash存一下比较一次
software_artisan 2016-08-23
  • 打赏
  • 举报
回复
software_artisan 2016-08-23
  • 打赏
  • 举报
回复
引用 19 楼 CGabriel 的回复:
借助一下字典能让问题简化好多

        private static int[] GetRandomIntValues(int expectedCouont)
        {
            Dictionary<int, int> container = new Dictionary<int, int>(expectedCouont);
            Random r = new Random();
            while(container.Count < expectedCouont)
            {
                int value = r.Next();
                if  (!container.ContainsKey(value))
                {
                    container.Add(value, value);
                }
            }
            int[] result = new int[expectedCouont];
            container.Values.CopyTo(result, 0);
            return result;
        }
测试 了一下速度

        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            int[] list = GetRandomIntValues(1000000);
            watch.Stop();
            Console.WriteLine(watch.Elapsed.TotalSeconds);
        }
结果是0.1299777 秒,不知道你能不能接受,反正我是觉得可以接受了。。
用guid做key,0-999999做value,然后一个排序就好了。。。。绝对随机,绝对唯一,但速度可能没你的快
小灰狼 2016-08-22
  • 打赏
  • 举报
回复
引用 17 楼 qq_20324803 的回复:
[quote=引用 13 楼 hemowolf 的回复:] 两种方式:
		static void f4() {
			
			Random rdm = new Random(DateTime.Now.Millisecond);
			
			// 记录开始时间
			DateTime t1 = DateTime.Now;
			// 生成一副1000W的牌
			int[] data = new int[1000 * 10000];
			for (int i = 0; i < data.Length; i++) {
				data[i] = i;
			}
			// 打乱这副牌
			for (int i = 0; i < data.Length; i++) {
				int idx1 = i;
				int idx2 = rdm.Next(data.Length);
				int tmp = data[idx1];
				data[idx1] = data[idx2];
				data[idx2] = tmp;
			}
			// 取这副牌的前100W条记录,结果放在 result 中
			int[] result = new int[100 * 10000];
			for (int i = 0; i < result.Length; i++) {
				result[i] = data[i];
			}
			// 终止时间
			DateTime t2 = DateTime.Now;
			// 打印总共用时,我测试是0.6510372秒
			Console.WriteLine((t2 - t1).TotalSeconds);
			for (int i = 0; i < 100; i++) {
				Console.Write(" ");
				Console.Write(result[i]);
			}
		}

		static void f5() {
			Random rdm = new Random(DateTime.Now.Millisecond);
			
			// 记录开始时间
			DateTime t1 = DateTime.Now;
			// 创建100W元素的数组,每个元素后一值随机比前一个增大
			int[] result = new int[100 * 10000];
			result[0] = 0;
			for (int i = 1; i < result.Length; i++) {
				result[i] = result[i - 1] + rdm.Next(10) + 1;
			}

			// 打乱
			for (int i = 0; i < result.Length; i++) {
				int idx1 = i;
				int idx2 = rdm.Next(result.Length);
				int tmp = result[idx1];
				result[idx1] = result[idx2];
				result[idx2] = tmp;
			}
			DateTime t2 = DateTime.Now;

			// 我测试用时 0.0510029 秒
			Console.WriteLine((t2 - t1).TotalSeconds);
			for (int i = 0; i < 100; i++) {
				Console.Write(" ");
				Console.Write(result[i]);
			}
		}
哇,看出编程水平了。人家一行代码搞定的。[/quote] 我的代码确实有点长,并且浪费空间 要想代码简洁,就直接用字典,只要随机数范围取得足够大,冲突发生机率就小
CGabriel 2016-08-21
  • 打赏
  • 举报
回复
借助一下字典能让问题简化好多

        private static int[] GetRandomIntValues(int expectedCouont)
        {
            Dictionary<int, int> container = new Dictionary<int, int>(expectedCouont);
            Random r = new Random();
            while(container.Count < expectedCouont)
            {
                int value = r.Next();
                if  (!container.ContainsKey(value))
                {
                    container.Add(value, value);
                }
            }
            int[] result = new int[expectedCouont];
            container.Values.CopyTo(result, 0);
            return result;
        }
测试 了一下速度

        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            int[] list = GetRandomIntValues(1000000);
            watch.Stop();
            Console.WriteLine(watch.Elapsed.TotalSeconds);
        }
结果是0.1299777 秒,不知道你能不能接受,反正我是觉得可以接受了。。
摇撼大地 2016-08-20
  • 打赏
  • 举报
回复
引用 13 楼 hemowolf 的回复:
两种方式:
		static void f4() {
			
			Random rdm = new Random(DateTime.Now.Millisecond);
			
			// 记录开始时间
			DateTime t1 = DateTime.Now;
			// 生成一副1000W的牌
			int[] data = new int[1000 * 10000];
			for (int i = 0; i < data.Length; i++) {
				data[i] = i;
			}
			// 打乱这副牌
			for (int i = 0; i < data.Length; i++) {
				int idx1 = i;
				int idx2 = rdm.Next(data.Length);
				int tmp = data[idx1];
				data[idx1] = data[idx2];
				data[idx2] = tmp;
			}
			// 取这副牌的前100W条记录,结果放在 result 中
			int[] result = new int[100 * 10000];
			for (int i = 0; i < result.Length; i++) {
				result[i] = data[i];
			}
			// 终止时间
			DateTime t2 = DateTime.Now;
			// 打印总共用时,我测试是0.6510372秒
			Console.WriteLine((t2 - t1).TotalSeconds);
			for (int i = 0; i < 100; i++) {
				Console.Write(" ");
				Console.Write(result[i]);
			}
		}

		static void f5() {
			Random rdm = new Random(DateTime.Now.Millisecond);
			
			// 记录开始时间
			DateTime t1 = DateTime.Now;
			// 创建100W元素的数组,每个元素后一值随机比前一个增大
			int[] result = new int[100 * 10000];
			result[0] = 0;
			for (int i = 1; i < result.Length; i++) {
				result[i] = result[i - 1] + rdm.Next(10) + 1;
			}

			// 打乱
			for (int i = 0; i < result.Length; i++) {
				int idx1 = i;
				int idx2 = rdm.Next(result.Length);
				int tmp = result[idx1];
				result[idx1] = result[idx2];
				result[idx2] = tmp;
			}
			DateTime t2 = DateTime.Now;

			// 我测试用时 0.0510029 秒
			Console.WriteLine((t2 - t1).TotalSeconds);
			for (int i = 0; i < 100; i++) {
				Console.Write(" ");
				Console.Write(result[i]);
			}
		}
哇,看出编程水平了。人家一行代码搞定的。
摇撼大地 2016-08-20
  • 打赏
  • 举报
回复
引用 12 楼 zbdzjx 的回复:
1、生成1~1000000,放到数组中。 2、for循环100万次,每次随机抽取两个数字,交换。 在我电脑上试了,2秒左右。
这不是随机。这都没有重复的。
摇撼大地 2016-08-20
  • 打赏
  • 举报
回复
引用 9 楼 sp1234 的回复:
[quote=引用 5 楼 xuzuning 的回复:] 你可先顺序生成 100玩的数,然后再打乱他,比如
Enumerable.Range(0, 100).OrderBy(x => Guid.NewGuid())
是这样的。 这不叫做“随机数”,这算法叫做随即洗牌。[/quote] 对。
software_artisan 2016-08-20
  • 打赏
  • 举报
回复
先生成0-999999的序列,然后随机取出一个,同时把取出的数字从序列里面删除,保证不重复
小灰狼 2016-08-19
  • 打赏
  • 举报
回复
两种方式:
		static void f4() {
			
			Random rdm = new Random(DateTime.Now.Millisecond);
			
			// 记录开始时间
			DateTime t1 = DateTime.Now;
			// 生成一副1000W的牌
			int[] data = new int[1000 * 10000];
			for (int i = 0; i < data.Length; i++) {
				data[i] = i;
			}
			// 打乱这副牌
			for (int i = 0; i < data.Length; i++) {
				int idx1 = i;
				int idx2 = rdm.Next(data.Length);
				int tmp = data[idx1];
				data[idx1] = data[idx2];
				data[idx2] = tmp;
			}
			// 取这副牌的前100W条记录,结果放在 result 中
			int[] result = new int[100 * 10000];
			for (int i = 0; i < result.Length; i++) {
				result[i] = data[i];
			}
			// 终止时间
			DateTime t2 = DateTime.Now;
			// 打印总共用时,我测试是0.6510372秒
			Console.WriteLine((t2 - t1).TotalSeconds);
			for (int i = 0; i < 100; i++) {
				Console.Write(" ");
				Console.Write(result[i]);
			}
		}

		static void f5() {
			Random rdm = new Random(DateTime.Now.Millisecond);
			
			// 记录开始时间
			DateTime t1 = DateTime.Now;
			// 创建100W元素的数组,每个元素后一值随机比前一个增大
			int[] result = new int[100 * 10000];
			result[0] = 0;
			for (int i = 1; i < result.Length; i++) {
				result[i] = result[i - 1] + rdm.Next(10) + 1;
			}

			// 打乱
			for (int i = 0; i < result.Length; i++) {
				int idx1 = i;
				int idx2 = rdm.Next(result.Length);
				int tmp = result[idx1];
				result[idx1] = result[idx2];
				result[idx2] = tmp;
			}
			DateTime t2 = DateTime.Now;

			// 我测试用时 0.0510029 秒
			Console.WriteLine((t2 - t1).TotalSeconds);
			for (int i = 0; i < 100; i++) {
				Console.Write(" ");
				Console.Write(result[i]);
			}
		}
健者天行 2016-08-19
  • 打赏
  • 举报
回复
引用 5 楼 xuzuning 的回复:
你可先顺序生成 100玩的数,然后再打乱他,比如
Enumerable.Range(0, 100).OrderBy(x => Guid.NewGuid())
简单、快捷 。
正怒月神 2016-08-18
  • 打赏
  • 举报
回复
楼上都说了。Enumerable.Range(1,100000)
showjim 2016-08-18
  • 打赏
  • 举报
回复
可以用插板法
我叫小菜菜 2016-08-18
  • 打赏
  • 举报
回复
引用 1 楼 From_TaiWan 的回复:
首先的给出这些数的范围,要是4字节整数的话,100万,这些数字占用空间接近4G,首先检查下你的内存大小 只要给定范围,可以将范围划分成几个段处理,将问题转化为排序,最后合并 估计得借助文件存储
100w≈1k*1k*4B≈4MB。我没算错吧。 在acm中new int[1000000]是常有的事。。 ----------- 用GUID转换为数字这个不错,就是数字有点大
xuzuning 2016-08-18
  • 打赏
  • 举报
回复
你可先顺序生成 100玩的数,然后再打乱他,比如
Enumerable.Range(0, 100).OrderBy(x => Guid.NewGuid())
加载更多回复(8)

110,502

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧