如何高效的產生一億組1到1億的隨機排列?

用c#和python numpy都做了嘗試,8g內存機器跑幾十分鐘沒完成,如何破?

謝謝各位老司機的指導。

補充說明:需要獲得一億組,1到1億的亂序排列。

items=range(1,100000001)

oklst=[]

for i in range(0,len(items)):

temp=items[:]

random.shuffle(temp)

oklst.append(temp)

循環一次要75秒,要循環1億次,有生之年就看不到了結果了。


謝邀,需要的範圍呢?直接把1到1億shuffle了可以嗎……大約需要一分多鐘吧

如果要求範圍,可以用random.sample(xrange(maxrand + 1), 100000000),應該也需要一分多鐘

====================================================================

一億組……你光把這些數據存進內存內存就炸了,存進硬碟硬碟也炸了,這可是2^54量級,16PB的數量……你為什麼不去租神威太湖之光……


我的電腦上20秒跑完:

In [122]: %timeit np.random.shuffle(np.arange(1e8))

1 loop, best of 3: 17.2 s per loop


謝邀。

我只有再來修改答案了,因為我沒注意到是1億組1-1億的數據,那我只能先問一下了 @ff0018 :

你的需求真的有那麼大?

我們先來看存儲:就算你優化存儲模式,自己寫一個二進位格式來做保存,1組數只要1G磁碟容量好了,1億組需要10萬T的存儲空間,2T家用硬碟大約400多RMB一個。大約2千萬人民幣了啊

再來看看計算量:簡單查了下資料,普通家用CPU的浮點運算力也就每秒幾百億次而已,就算加上GPU,做到了每秒一組,1億組也需要三年時間。所以單台PC是無法完成你的計算需求的。

結論:要麼題主好好思考一下自己的需求,是不是可以用更高級的演算法來代替天量數據;要麼準備10萬T的數據存儲空間去超算中心下訂單吧。

-----------------------------------------------------以下是我看錯的題目,計算了1-1億的隨機序列一次。

題主更新了內容:

既然是產生1到1億的隨機序列,那直接產生一個序列,然後用random打亂一次就好了啊,題主的代碼完全不需要循環億次啊,只需要random.shuffle一次就打亂了。另外 @知之 的方案也是如此。

import random
def myrandom():
itmes = [x for x in range(10000000)]
random.shuffle(itmes)

我的機器內存太小,只能跑一千萬,大約是21.8秒,跑1億內存要出錯。

跑一千萬的結果:

------------------------------------以下是老題目答案,先不刪除了。

題目寫得不夠詳細,那我就只考慮產生,也不考慮類別和大小了,也不考慮輸出了

我認為要想快必須是不驗重

但是既然題目是要求不重複,那我們設計一種絕對不會重複的產生辦法

比如說隨機數乘以系統時間:time.time()*random.random()

我的N年前的破電腦上產生1億個這樣的數字,也只用了52秒。

電腦配置:


這段代碼我機器跑20秒左右。演算法的思路就是遍歷每個元素,並跟一個隨機位置的數據交換。

static void Main(string[] args)
{
int length = 100000000;
int[] array = new int[length];
for(int i = 0; i &< length; i++) { array[i] = i; } Random random = new Random(); for (int i = 0; i &< length; i++) { int index = random.Next(0, length); int temp = array[i]; array[i] = array[index]; array[index] = temp; } //Console.WriteLine(string.Join(",", array)); Console.WriteLine("Done"); Console.ReadLine(); }


搜到一篇文章,剛好契合題主的問題,搬運一下

http://www.cnblogs.com/Geometry/archive/2011/01/25/1944582.html


一億個不重複的隨機數?什麼類型?範圍是什麼,若是int 範圍也是1億辣么不重複不就是1到1億么?

我已經開始懷疑我理解的不對了,請補充需求


這樣是105s?


為啥不能用呢?


本質上是把給定的數組亂序

把每個位置都與隨機位置交換一下就好~_~

using System;
using System.Linq;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var arr = Enumerable.Range(1, 100000000).ToArray();

var startTime = DateTime.Now;
Randomize(arr);
Console.WriteLine(DateTime.Now - startTime);

//輸出太慢,隨便打30個出來看看就行了
Console.WriteLine(string.Join(" ", arr.Take(30)));
}

static void Randomize(int[] arr)
{
var r = new Random();
var length = arr.Length;
for (var i = 0; i &< length; i++) { //交換第i個與第隨機個 var j = r.Next(length); var tmp = arr[j]; arr[j] = arr[i]; arr[i] = tmp; } } } }

00:00:06.8644622

74126238 27251886 12653525 52215136 20302563 30930142 12847246 73436911 14694144 31472149 62573709 9793073 33085182 4275788 32783670 42466724 96079139 1678872 48412511 27698924 89272676 8074262 28219532 42970778 98212619 97204588 78149759 70340918 79619810 64839797

請按任意鍵繼續. . .


先生成1到1e9 的順序集合…然後隨機交換…


==========高能演算法===============

直接取1億個隨機數就可以,因為都是偽隨機數,周期很長,不會重複

不查重:1.8秒 o n

查重:10秒 o nlog n

重複了可以重新取,無所謂,人有多大膽,地有多大產

==========以下為原回答============

這個問題難點在於平均分布,用重複重取可以保證

期望為常數,o1複雜度。這個常數和值域和隨機次數有關,值域遠大的時候,非常接近1,我算過。

一般隨機數都是long,就算是int也是20多億,很小的常數記錄重複用hash優化為o1複雜度。所以最終結果是on,也就是接近一億次隨機和hash即可解決問題空間時間都是on,感覺不錯

內存佔用就算是long也才8億byte,不到1g(實際TreeSet佔用不到3g,HashSet不到10g)

java:

生成隨機數時間:1.8秒 o n

TreeSet時間:210秒 o nlog n

HashSet時間:128秒 o n

由於java集合存的是對象,不是基本數據類型,所以性能很差。


瀉藥。跟題主一起等大神。

不過,用python跑一億隨機數,居然不死機


我猜想你想要的是shuffle,shuffle不是隨機的,當你前面(除了最後一個數)都確定了後,最後一個也就確定了。


我寫過類似的。

生成n位無規律的不重複的字元串。

無規律和不重複怎麼保證呢,產生的性能又如何保證呢,下面我們一起走進科學。

首先,字元串由a...z和A...Z和0...9組成,共62種。

即每一位有62種可能。

假設產生一個四位的字元串,

第一種可能是AAAA

第二種可能是AAAB

第三種可能是AAAC

。。。

這樣下來,絕對能保證不重複。

但這樣還不夠,因為是順序的。

那麼怎麼保證無序呢。

也簡單,14776336=62*62*62*63,那麼必然有一個集合[1,100000000)

存在一個數字——100000000,大於14776336並且是個很好看的數字。有這個集合有什麼用呢?

簡單的說,在集合里必然存在1的鏡像數字1000000,2的鏡像數字2000000,…,9的鏡像數字是90000000,10的鏡像數字01000000,11的鏡像數字11000000,…,

這樣,原本第一種排解組合AAAA,第二種排列組合AAAB,就不按順序取了,按這個數字的鏡像數字取。

即第一個隨機字元串取第10000000個排列組合,第二個字元串取第20000000個排列組合…

這樣,既不重複又看上去是無序的。

而且,不用事先產生,可以隨時計算出來,計算效率其實是很高的。

回到題主的問題來,題主需要的是純數字,也簡單,只要在產生的字元串上接一個密碼本就好了。

比如第一位的字母a代表97,第一位的字母b代表98,…,第二位的字母a代表79,第二位的字母b代表89,…,就行了。


推薦閱讀:

如何配置Visual Studio 2017作為Python開發環境?
好像發現了一個不錯的小工具

TAG:Python | 演算法 | C# |