【问题标题】:fastest way to convert bitstring numpy array to integer base 2将位串numpy数组转换为整数基数2的最快方法
【发布时间】:2016-09-19 06:33:15
【问题描述】:

我有一个由位串组成的 numpy 数组,我打算将位串转换为以 2 为基数的整数,以便执行一些异或位运算。我可以用这个在python中将字符串转换为以2为底的整数:

int('000011000',2)

我想知道在 numpy 中是否有更快更好的方法来做到这一点。我正在研究的一个 numpy 数组的例子是这样的:

array([['0001'],
       ['0010']], 
      dtype='|S4')

我希望将其转换为:

array([[1],[2]])

【问题讨论】:

    标签: python arrays numpy int bitstring


    【解决方案1】:

    可以使用np.fromstring 将每个字符串位分离成uint8 类型的数字,然后使用一些带有矩阵乘法的数学 来转换/减少为十进制格式。因此,以A 作为输入数组,一种方法是这样 -

    # Convert each bit of input string to numerals
    str2num = (np.fromstring(A, dtype=np.uint8)-48).reshape(-1,4)
    
    # Setup conversion array for binary number to decimal equivalent
    de2bi_convarr = 2**np.arange(3,-1,-1)
    
    # Use matrix multiplication for reducing each row of str2num to a single decimal
    out = str2num.dot(de2bi_convarr)
    

    示例运行 -

    In [113]: A    # Modified to show more variety
    Out[113]: 
    array([['0001'],
           ['1001'],
           ['1100'],
           ['0010']], 
          dtype='|S4')
    
    In [114]: str2num = (np.fromstring(A, dtype=np.uint8)-48).reshape(-1,4)
    
    In [115]: str2num
    Out[115]: 
    array([[0, 0, 0, 1],
           [1, 0, 0, 1],
           [1, 1, 0, 0],
           [0, 0, 1, 0]], dtype=uint8)
    
    In [116]: de2bi_convarr = 2**np.arange(3,-1,-1)
    
    In [117]: de2bi_convarr
    Out[117]: array([8, 4, 2, 1])
    
    In [118]: out = str2num.dot(de2bi_convarr)
    
    In [119]: out
    Out[119]: array([ 1,  9, 12,  2])
    

    可以建议一种替代方法来避免np.fromstring。使用这种方法,我们将在开始时转换为 int 数据类型,然后将每个数字分开,这应该相当于前面方法中的str2num。其余代码将保持不变。因此,另一种实现方式是 -

    # Convert to int array and thus convert each bit of input string to numerals
    str2num = np.remainder(A.astype(np.int)//(10**np.arange(3,-1,-1)),10)
    
    de2bi_convarr = 2**np.arange(3,-1,-1)
    out = str2num.dot(de2bi_convarr)
    

    运行时测试

    让我们对迄今为止列出的所有解决问题的方法进行计时,包括@Kasramvd's loopy solution

    In [198]: # Setup a huge array of such strings
         ...: A = np.array([['0001'],['1001'],['1100'],['0010']],dtype='|S4')
         ...: A = A.repeat(10000,axis=0)
    
    
    In [199]: def app1(A):             
         ...:     str2num = (np.fromstring(A, dtype=np.uint8)-48).reshape(-1,4)
         ...:     de2bi_convarr = 2**np.arange(3,-1,-1)
         ...:     out = str2num.dot(de2bi_convarr)    
         ...:     return out
         ...: 
         ...: def app2(A):             
         ...:     str2num = np.remainder(A.astype(np.int)//(10**np.arange(3,-1,-1)),10)
         ...:     de2bi_convarr = 2**np.arange(3,-1,-1)
         ...:     out = str2num.dot(de2bi_convarr)    
         ...:     return out
         ...: 
    
    In [200]: %timeit app1(A)
    1000 loops, best of 3: 1.46 ms per loop
    
    In [201]: %timeit app2(A)
    10 loops, best of 3: 36.6 ms per loop
    
    In [202]: %timeit np.array([[int(i[0], 2)] for i in A]) # @Kasramvd's solution
    10 loops, best of 3: 61.6 ms per loop
    

    【讨论】:

      【解决方案2】:

      由于KISS principle,我想建议以下使用列表理解的方法:

      >>> np.array([[int(i[0], 2)] for i in a])
      array([[1],
             [2]])
      

      【讨论】:

        猜你喜欢
        • 2016-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-20
        • 1970-01-01
        • 1970-01-01
        • 2020-02-18
        • 2010-09-19
        相关资源
        最近更新 更多