我正在尝试编写一个函数,它可以将一些数据归零,直到其长度等于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

但我不知道怎样才能更有效率。

最佳答案

你不需要做很多你正在做的事情-你只需要找出下一个2的幂,你需要扩展你的数组的长度,然后你可以调用数组上的pad,一次将它填充到你需要的长度。
这使用了另一个关于Python中获得2的下一个幂的最快方法的问题中的shift_bit_length

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])

10-08 11:08