2017-03-01 137 views
2

我想改善我的代碼,將隨機生成的數字排序到區間區間中,以便分析隨機數生成器的準確性。目前我的排序是由20個elif語句執行的(我只有python的入門知識),結果我的代碼需要很長時間才能執行。我怎樣才能更有效地將數字數據分類爲間隔,並只保存間隔中的數字頻率?計數範圍區間內的數字數據的頻率

from datetime import datetime 
startTime = datetime.now() 
def test_rand(points): 
    import random 
    d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,d20 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 
    # these variables will be used to count frequency of numbers into 20 intervals: (-10,-9], (-9,-8] ... etc 
    g1,g2,g3,g4,g5,g6,g7,g8,g9,g10,g11,g12,g13,g14,g15,g16,g17,g18,g19,g20 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 
    # these variables will be used to count frequency of every 20 numbers into 20 intervals: (-200,-180], (-180,-160] ... etc 
    y = 0 
    n = 0 
    for i in range(points): 
     x = random.uniform(-10.0,10.0) 
     while n < 20: 
      y += x 
      n += 1 
      break 
     if n == 20: 
      if y < -180: 
       g1 += 1 
      elif y < -160 and y > -180: 
       g2 += 1 
      elif y < -140 and y > -160: 
       g3 += 1 
      elif y < -120 and y > -140: 
       g4 += 1 
      elif y < -100 and y > -120: 
       g5 += 1 
      elif y < -80 and y > -100: 
       g6 += 1 
      elif y < -60 and y > -80: 
       g7 += 1 
      elif y < -40 and y > -60: 
       g8 += 1 
      elif y < -20 and y > -40: 
       g9 += 1 
      elif y < 0 and y > -20: 
       g10 += 1 
      elif y < 20 and y > 0: 
       g11 += 1 
      elif y < 40 and y > 20: 
       g12 += 1 
      elif y < 60 and y > 40: 
       g13 += 1 
      elif y < 80 and y > 60: 
       g14 += 1 
      elif y < 100 and y > 80: 
       g15 += 1 
      elif y < 120 and y > 100: 
       g16 += 1 
      elif y < 140 and y > 120: 
       g17 += 1 
      elif y < 160 and y > 140: 
       g18 += 1 
      elif y < 180 and y > 160: 
       g19 += 1 
      elif y > 180: 
       g20 += 1 
      y *= 0 
      n *= 0 

     if x < -9: 
      d1 += 1 
     elif x < -8 and x > -9: 
      d2 += 1 
     elif x < -7 and x > -8: 
      d3 += 1 
     elif x < -6 and x > -7: 
      d4 += 1 
     elif x < -5 and x > -6: 
      d5 += 1 
     elif x < -4 and x > -5: 
      d6 += 1 
     elif x < -3 and x > -4: 
      d7 += 1 
     elif x < -2 and x > -3: 
      d8 += 1 
     elif x < -1 and x > -2: 
      d9 += 1 
     elif x < 0 and x > -1: 
      d10 += 1 
     elif x < 1 and x > 0: 
      d11 += 1 
     elif x < 2 and x > 1: 
      d12 += 1 
     elif x < 3 and x > 2: 
      d13 += 1 
     elif x < 4 and x > 3: 
      d14 += 1 
     elif x < 5 and x > 4: 
      d15 += 1 
     elif x < 6 and x > 5: 
      d16 += 1 
     elif x < 7 and x > 6: 
      d17 += 1 
     elif x < 8 and x > 7: 
      d18 += 1 
     elif x < 9 and x > 8: 
      d19 += 1 
     elif x > 9: 
      d20 += 1 

    return d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,d18,d19,d20,g1,g2,g3,g4,g5,g6,g7,g8,g9,g10,g11,g12,g13,g14,g15,g16,g17,g18,g19,g20 

print(test_rand(100000000))  

print (datetime.now() - startTime) 

該代碼旨在用隨機數執行2個函數。首先是將數字排序爲20個區間(因此,每個區間應該有5%的數字)。二是這些總結生成的每個20個數字,並放入20周新的時間間隔(一正常曲線應觀察)

@tristan我修改您的代碼用於執行上述:

for idx in range(points): 
     val_1 = uniform(-10, 10) 
     val_20 += val_1 
     if (idx + 1) % 20 == 0: 
      counter2[bisect(occ2, val_20)] += 1 
      counter1[bisect(occ1, val_1)] += 1 
      val_20 = 0 
      val_1 = 0 
     else: 
      counter1[bisect(occ1, val_1)] += 1 
      val_1 = 0 

雖然這方法只保存6秒(1:54 - > 1:48),FAR更有組織,更易於查看。謝謝您的幫助!

+0

改爲使用兩個列表。我沒有看到while循環的重點。用一些數學來計算索引。 –

回答

2

假設數據總是可以被分配給您的時間間隔(你可以前檢查)之一,採用bisect.bisect()將是一個高效,緊湊的方式:

from bisect import bisect 
from random import randint 

occ1 = [-9 + 1 * i for i in range(19)] 
occ2 = [-180 + 20 * i for i in range(19)] 
data = [randint(-10, 10) for _ in range(100)] 
counter1, counter2 = {i: 0 for i in range(20)}, {i: 0 for i in range(20)} 

for idx, element in enumerate(data): 
    if (idx + 1) % 20 == 0: 
     counter2[bisect(occ2, element)] += 1 
    else: 
     counter1[bisect(occ1, element)] += 1 

平分( )函數返回位置,其中元素應該插入到像occ這樣的有序數組中以維持順序。在occ中有19個值,可以插入20個不同的位置。也就是說,在第一個之前,在任何元素之間或之後。這對應於你的20個間隔。唯一要注意的是,e。 G。一個元素小於或大於您的區間的上限或下限,它仍將被分配到最低或最高區間。生成關於區間範圍的隨機數將會阻止這一點。

從你的問題我不知道你是否想要累積一些隨機數或只檢查點的列表,其中每20個值執行不同的檢查。 該解決方案可以很容易地適應累積的隨機數,直到20次迭代達到:

from bisect import bisect 
from random import uniform 

points, value = 100000000, 0 
occ1 = [-9 + 1 * i for i in range(19)] 
occ2 = [-180 + 20 * i for i in range(19)] 
counter1, counter2 = {i: 0 for i in range(20)}, {i: 0 for i in range(20)} 

for idx in range(points): 
    value += uniform(-10, 10) 
    if (idx + 1) % 20 == 0: 
     counter2[bisect(occ2, value)] += 1 
     value = 0 
    else: 
     counter1[bisect(occ1, value)] += 1 

這個運行在100秒我的機器上100M點。

+0

@qwop這是否適合你想要做的事情? – Tristan

+0

感謝您解釋平分功能。我想我已經能夠正確修改這個代碼來合計隨機數 – qwop