我有一个由复数组成的 numpy 数组,需要创建一个包含四舍五入的实部和虚部的新数组,其中四舍五入是向零或向无穷大。
在 stackoverflow 上有一些使用 decimal 包的建议,它允许指定不同类型的舍入。对于复数数组 x
,以下代码有效,但速度非常慢:
rounded_array = np.array([
float(Decimal(x.real).quantize(0, rounding=ROUND_HALF_DOWN)) + 1j * \
float(Decimal(x.imag).quantize(0, rounding=ROUND_HALF_DOWNs)) for x in arr])
有哪些简单但更快的替代方案?
建议使用此解决方案:
How to always round up a XX.5 in numpy
但是,它仅适用于实际数组,并且比下面建议的解决方案慢得多。
快速就地舍入减半:
arr = arr.view(float)
m = arr % 1. <= .5
arr[m] = np.floor(arr[m])
arr[~m] = np.ceil(arr[~m])
arr = arr.view(complex)
(使用 m = arr % 1. < .5
取整)
如果您需要一个新数组而不是就地更改现有数组,请将第一行更改为 arr = arr.view(float).copy('K')
.
对于 1000 个元素的数组,这比原始解决方案快大约 100 倍。
UPDATE 根据以下评论为负数:
m = arr % 1. == .5
arr[m] = np.trunc(arr[m])
arr[~m] = np.round(arr[~m])
时间
x = np.arange(-1000, 1000, .1)
arr = x + 1j * x
%%timeit
rounded_array = np.array([
float(Decimal(x.real).quantize(0, rounding=ROUND_HALF_DOWN)) + 1j * \
float(Decimal(x.imag).quantize(0, rounding=ROUND_HALF_DOWN)) for x in arr])
1.83 s ± 27.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
arr1 = arr.view(float).copy('K')
m = arr1 % 1. == .5
arr1[m] = np.trunc(arr1[m])
arr1[~m] = np.round(arr1[~m])
arr1 = arr1.view(complex)
1.78 ms ± 18.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)