2016-01-06 39 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