2016-01-06 40 views
2

我正試圖寫一個函數,可以零填充一些數據,直到它的長度等於最接近的更高的2次冪。我也想成爲能夠做一定數量的迭代。現在這是我的函數:零填充數據,直到它的長度等於2的冪

def pad_to_next_2n(array, iterations = 1): 
    n = 1 
    while n <= iterations: 
     l = len(array) 
     padding = l +1 #incase array is already length equal to 2^n 
     while np.log2(padding) % 1 != 0: 
      padding += 1 
     if l % 2 == 0: 
      total_padding = padding - l 
      array = np.pad(array, (total_padding/2,), 'constant') 
      n += 1 
     else: 
      total_padding = padding - l 
      left_padding = (total_padding - 1)/2 
      right_padding = total_padding - left_padding 
      print total_padding 
      print left_padding 
      print right_padding 
      array = np.pad(array, (left_padding, right_padding), 'constant') 
      n += 1 
    return array 

這並不工作,但它真的很慢的迭代大於5。我在想,如果有人可以幫助提高這個速度或看到一個更好的方式來做到這一點。我相信最大的問題來自於

while np.log2(padding) % 1 != 0: 
       padding += 1 

部分,但我不知道如何使效率更高。

+0

它你的意思是什麼目前尚不清楚「我一直希望能夠做一定數量的這種迭代的。」爲什麼不一次性計算最終大小('2 **(int(np.log2(padding))+ 1)'可以做到這一點),然後填充數組? – Evert

+0

我的意思並不總是,這是一個錯字 – greenthumbtack

回答

2

你不需要做很多你正在做的事情 - 你只是想找出下一個你需要將數組的長度擴展到2的力量,然後你可以調用pad陣列將它填充到你需要的長度。

這使用shift_bit_length來自另一個關於在Python中獲得2的下一個冪的最快方法。

import numpy as np 

def shift_bit_length(x): 
    return 1<<(x-1).bit_length() 

def padpad(data, iterations = 1): 
    narray = data 
    for i in xrange(iterations): 
     length = len(narray) 
     diff = shift_bit_length(length + 1) - length 
     if length % 2 == 0: 
      pad_width = diff/2 
     else: 
      # need an uneven padding for odd-number lengths 
      left_pad = diff/2 
      right_pad = diff - left_pad 
      pad_width = (left_pad, right_pad) 
     narray = np.pad(narray, pad_width, 'constant') 
    return narray 

一些測試:

>> arr = np.array([1, 2]) 

>> padpad(arr, 1) 
Out[2]: array([0, 1, 2, 0]) 

>> len(padpad(arr, 1) 
Out[3]: 4 

>> padpad(arr, 5) 
Out[4]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) 

>> len(padpad(arr, 5)) 
Out[5]: 32 

>> padpad(arr, 8) 
Out[6]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0]) 
+0

這僅適用於具有均勻長度的陣列。它能夠使用奇數長度的數組嗎? – greenthumbtack

+0

@greenthumbtack呃 - 在代碼中添加(改編自您的原創),支持奇數長度的數組。 – birryree

5

您不必通過每次增加一個填充來迭代。只需計算你需要的下一個尺寸。下一個尺寸是2**int(log2(current_size)+1)

然後你可以減去current_size並知道你需要多少填充。

+1

FYI,['int' /'long'的'.bit_length()'方法(在2.7+中可用)](https://docs.python.org/2 /library/stdtypes.html#int.bit_length)可以計算出更有效/直接表示值所需的位(並避免承認不太可能的浮點錯誤)。 '1 << current_size.bit_length()'似乎是等價的(除非'current_size == 0';'log2'拋出異常,'.bit_length()'返回'0';你可以強制它返回'1'而不會通過執行'(current_size | 1).bit_length()')來影響其他場景中的行爲。 – ShadowRanger