python将小数数组转换为二进制数的效率

2024-10-01 07:41:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我做了一个代码,在一个文件中读取256x256矩阵,将它们转换成二进制数,读取其中的一部分,生成另外两个256x256矩阵文件。我想它正在做我想做的,但是处理一个文件需要几分钟。有什么更有效的代码建议吗?在

这是我的密码。在

#Read in file
f = open(path, 'r')
l = [list(map(int, line.split(' '))) for line in f]
a = np.array(l)
A = a.ravel()

#Convert to binary
bnry = ()
for data in A:
    bnry = np.append(bnry, bin(data))

#Extract two data from each number and store them to 'THL' and 'THH'
thl = ()
thh = ()
THL = ()
THH = ()
for ths in bnry:
    thl = int(ths[2:14], 2)
    THL = np.append(THL, thl)
    thh = int(ths[-12:], 2)
    THH = np.append(THH, thh)

#Save 'THL' and 'THH' to text files
np.savetxt('THL.txt', np.reshape(THL, (256,256)), fmt='%.4g', delimiter=' ')
np.savetxt('THH.txt', np.reshape(THH, (256,256)), fmt='%.4g', delimiter=' ')

解决方案 多亏了oliverw,我能够得到一个比我几分钟长的代码快得多的更短的代码。基本上是这样

^{pr2}$ 我还需要更多的学习,熟悉他们是如何工作的,但是他们工作得太好了!在


Tags: and文件to代码infordatanp
1条回答
网友
1楼 · 发布于 2024-10-01 07:41:33

你要提取一系列整数的前12位和后12位。这是两个截然不同的问题。后者是最容易的。在

首先,让我们从使用numpy的方便方法从文本文件中读入数据,而不是捏造我们自己的(更可能是不太理想的)函数:

a = np.fromfile(file, dtype=np.uint32, sep=' ')  # alternative: np.genfromtxt

接下来,我们来解决一个简单的问题:从a中提取最低的12位:

^{pr2}$

这是一个矢量化的操作,所以它非常高效而且非常快速。在

然而,获得前12位是另一个问题,因为它取决于数字本身。我的猜测是,这实际上不是你想做的,而是有人要求你从一些整数中提取12个“最高”位,当它们被解释为具有固定的位数时。用“最高的3位”来解释会更清楚:

如果你需要一个数字的3个最高位,比如说20,你可以把20解释为写成0b10100,在这种情况下,最高的3位是101,这是十进制数5。但是,如果您将20解释为0b0010100,那么有2个前导零,那么最高的3位将是001,这是十进制数1。实际上没有多少操作需要考虑(最小)二进制表示的长度,我想这也是为什么你说“我认为它在做我想要的”。在

因此,更有可能的是,你的数字将被解释为二进制格式,长度固定。看看你提到的最大值268374015,这个长度可能是28位(即使看起来不太可能,32位更常见)。但是,假设它是28位,并且您只想提取前12位,您可以使用与之前相同的技巧:

np.logical_and(a, (2**12 - 1)<<16) >> 16

注意,>>和{}是{a1}。在

不过,我对你的数据做了几个假设(很明显,你只处理整数,因为你要用int()来转换一切),当然还有你的问题。在

但是,如果您真的希望从这些数字的前12位开始,从最高有效位开始,那么下面的代码将向您显示:

  1. 对for循环的重新实现,效率略高一些(method_old()
  2. 该算法的矢量化实现(method_new()

以及他们在我机器上的执行时间。在

import numpy as np

a = np.random.random_integers(0, 268374016, (512,512))

def method_new(nbr_select_bits=12):
    high_bits = np.empty_like(a)
    for bit in range(32, nbr_select_bits -1, -1):
        mask = a < 2**bit
        shift = bit - nbr_select_bits
        bitmask = (2**nbr_select_bits - 1) << shift
        high_bits[mask] = np.bitwise_and(a[mask], bitmask) >> shift
    low_bits = np.bitwise_and(a, 2**nbr_select_bits - 1)
    return high_bits, low_bits

def method_old(nbr_select_bits=12):
    thl = np.empty(a.size, dtype=np.uint32)
    thh = np.empty(a.size, dtype=np.uint32)
    for enu, data in enumerate(a.ravel()):
        thl[enu] = int(bin(data)[2:2+nbr_select_bits], 2)
        try:
            thh[enu] = int(bin(data)[-nbr_select_bits:], 2)
        except ValueError:  # because 'int("b11", 2)' fails
            thh[enu] = int(bin(data)[-(nbr_select_bits+1):], 2)
    return thl.reshape(a.shape), thh.reshape(a.shape)

from timeit import timeit
new_t = timeit('method_new()', setup='from __main__ import method_new', number=1)
old_t = timeit('method_old()', setup='from __main__ import method_old', number=1)
print('Old method ran in {:.2f}ms,\nNew method ran in {:.2f}ms.\n'
    'Speedup: {:.1f}x'.format(old_t*1000, new_t*1000, old_t/new_t))))
# Output:
# Old method ran in 473.97ms,
# New method ran in 60.18ms.
# Speedup: 7.9x

相关问题 更多 >