2015-11-02 38 views
0

我寫了一個腳本,它不是給出一組數據的實際平均值,而是返回一個包含大多數數據點的窗口。讓我告訴一些代碼:使用高數字時函數速度變慢

time.tic() 
var selectedAverage = 0; 
var highestPointCount = 0; 
for (var i = 1; (i*step) <= maxValue; i++) { 
    var dataPointCount = 0; 
    for (var j = 0; j < myArray.length; j++) { 
     if (myArray[j] >= minValue+(i-1)*step && myArray[j] <= minValue+i*step) { 
      dataPointCount++; 
     } 
    } 
    if (dataPointCount > highestPointCount) { 
     highestPointCount = dataPointCount; 
     selectedAverage = (minValue+(i-1)*step)+Math.round(0.5*step); 
    } 
} 
console.log(time.toct().ms) 
return selectedAverage; 

首先步進值是通過從最大值減去最小值,然後由10決定所以有10個「水平」窗口來計算。然後腳本計算每個窗口內數據點的數量並返回適當的平均值。

但是,當傳遞一個數字較大的數組(例如1.000.000)時,腳本會顯着減慢(有時超過200次)。數組長度大致爲200,但始終長度相同,因此它必須與實際值相關聯。任何想法哪裏出錯?

編輯: 的代碼來獲得步長值:

var minValue = myArray.min(); 
var maxValue = myArray.max(); 
var step = Math.round((maxValue-minValue)/10); 
if (step === 0) { 
    step = 1 
} 

的.min()和的.max()是附接至陣列原型。但這一切都非常快。我已經測量了每一步,並且它是減慢的for循環。

+0

不確定步驟是什麼? – juvian

+0

沒有看到更多的代碼,很難說代碼應該做什麼,但問題與嵌套循環有關,它看起來像代碼做的工作比應該做的要多得多。 – Pointy

+0

當然你可以遍歷數組** **一次**,並在數值上確定每個值所處的「步長」。不需要一遍又一遍地搜索整個數組。 – Pointy

回答

1

如果我明白你的算法正確,這應該刪除所有unnecesary計算和快得多:

var arr = []; 
var maxQty=0; 
var wantedAverage = 0; 
for (var j = 0; j < 11; j++) { 
    arr[j]=0; 
} 
for (var j = 0; j < myArray.length; j++) { 
    var stepIndex = Math.floor((myArray[j]-minValue)/step) 
    arr[stepIndex]+=1; 

    if(arr[stepIndex] > maxQty){ 
     wantedAverage = minValue + stepIndex*step +Math.round(0.5*step); 
     maxQty = arr[stepIndex] 
    } 
} 
console.log(maxQty, wantedAverage) 

我們只是遍歷數組的每個元素只有一次,並計算窗口指數它屬於,在數組中添加一個。然後我們更新wantedAverage,如果我們在窗口中找到更多的點數

+0

@SecondLemon這裏是一個小例子:http://jsfiddle.net/vy7yL3jx/ – juvian

+0

我現在正在實施它。我會很快讓你知道! – SecondLemon

+0

我真的很喜歡你的方法。但似乎還有些不對。它每次都返回0,0。我會親自看看這裏有什麼不同。初看起來,它應該工作。編輯:哎呀我的錯誤。將步驟計算註釋掉。完美的作品! – SecondLemon

1

有2個不同的東西,我覺得你的問題:

  1. 刪除不必要/重複計算

裏面你有minValue+(i-1)*stepminValue+i*stepminValue相同的值來計算每次的嵌套代碼, istep。 你應該在第二個for循環,它成爲前拉起來:

var dataPointCount = 0; 
var lowerLimit = minValue+(i-1)*step; 
var higherLimit = minValue+1*step; 
for (var j = 0; j < myArray.length; j++) { 
    if (myArray[j] >= lowerLimit && myArray[j] <= higherLimit) { 
     dataPointCount++; 
    } 
} 
  • 你,當你正在處理大數據陣列可能是由內存交換導致了嚴重的性能下降。從您的角度來看,您正在處理單個數組實例,但是當您擁有如此龐大的陣列時,JavaScript VM不太可能訪問連續的內存空間來保存所有這些值。 JavaScript虛擬機很可能必須處理它從操作系統獲得的多個內存塊,並且必須花費額外的努力來翻譯讀/寫過程中的哪個值。
  • +0

    感謝您的第一個建議,但它並沒有提高速度。它從10秒553ms變爲10秒513ms。主要問題是Pointy發現的問題(在主帖的評論中)。 – SecondLemon

    相關問題