为什么列表操作比numpy数组操作慢

时间:2019-03-31 11:48:56

标签: python arrays performance numpy encryption

我正在做一个使用RSA算法加密数据的项目,为此,我将一个.wav文件作为输入,并使用wavfile进行了读取,我可以应用密钥了(3, 25777),但是当我应用解密密钥(16971,25777)时,给出的输出错误是这样的:

我得到的输出:

                    [[     0 -25777]
                    [     0 -25777]
                    [     0 -25777]
                    ...
                    [-25777 -25777]
                    [-15837 -15837]
                    [ -8621      1]]

我想要的输出:

                    [[ 0 -1]
                    [ 2 -1]
                    [ 2 -3]
                    ...
                    [-9 -5]
                    [-2 -2]
                    [-4  1]]

这仅在数组的解密部分发生,所以我决定将2d数组转换为2d列表。之后,它给了我想要的输出,但是将键应用于列表的所有元素要花费很多时间(16分钟,如果是数组,则为2秒)。我不明白为什么会这样,是否还有其他解决办法?

这是程序的加密和解密部分:

    #encryption
    for i in range(0, tup[0]): #tup[0] is the no of rows
        for j in range(0, tup[1]): #tup[1] is the no of cols
            x = data[i][j] 
            x = ((pow(x,3)) % 25777) #applying the keys
            data[i][j] = x #storing back the updated value

    #decryption
    data= data.tolist() #2d array to list of lists 
    for i1 in (range(len(data)):
        for j1 in (range(len(data[i1]))):
            x1 = data[i1][j1] 
            x1 = (pow(x1, 16971)%25777) #applying the keys
            data[i1][j1] = x1 

期待提出建议。谢谢。

1 个答案:

答案 0 :(得分:4)

pow(x1, 16971)之类的东西应该让您暂停一下。对于几乎所有的整数x1,这都会产生64位int无法保存的结果。这是numpy给出错误结果的原因,因为numpy在最常见的平台上使用64位或32位整数。这也是纯Python速度慢的原因,因为尽管它可以处理大整数,但代价昂贵。

解决此问题的一种方法是在乘法之间应用模数,从而使数字保持较小并可以通过64位算术轻松处理。

这是一个简单的实现:

def powmod(b, e, m):
    b2 = b                         
    res = 1                        
    while e:                       
        if e & 1:                  
            res = (res * b2) % m   
        b2 = (b2*b2) % m        
        e >>= 1                 
    return res

例如:

>>> powmod(2000, 16971, 25777)
10087
>>> (2000**16971)%25777
10087
>>> timeit(lambda: powmod(2000, 16971, 25777), number=100)
0.00031936285085976124
>>> timeit(lambda: (2000**16971)%25777, number=100)
0.255017823074013