【问题标题】:Is it possible to create a numpy.ndarray that holds complex integers?是否可以创建一个包含复整数的 numpy.ndarray?
【发布时间】:2012-12-01 13:26:15
【问题描述】:

我想创建 numpy.ndarray 对象,其中包含复杂的整数值。 NumPy 确实具有内置的复杂支持,但仅适用于浮点格式(floatdouble);例如,我可以用dtype='cfloat' 创建一个ndarray,但没有类似的dtype='cint16'。我希望能够创建包含使用 8 位或 16 位整数表示的复杂值的数组。

我在this mailing list post from 2007 找到有人询问此类支持。他们建议的唯一解决方法是定义一个新的 dtype 来保存整数对。这似乎将每个数组元素表示为 2 个值的元组,但尚不清楚需要完成哪些其他工作才能使生成的数据类型与算术函数无缝协作。

我还考虑了另一种基于 registration of user-defined types 和 NumPy 的方法。如果它运行良好,我没有问题去 C API 进行设置。但是,documentation for the type descriptor strucure 似乎表明该类型的 kind 字段仅支持有符号/无符号整数、浮点和复数浮点数值类型。目前尚不清楚我是否能够尝试定义一个复杂的整数类型。

对可行的方法有什么建议吗?

编辑:还有一件事;我选择的任何方案都必须能够在不执行复制的情况下包装现有的复杂整数缓冲区。也就是说,我希望能够使用 PyArray_SimpleNewFromData() 将缓冲区公开给 Python,而不必先复制缓冲区。缓冲区已经是交错的实数/虚数格式,并且可以是int8_tint16_t 的数组。

【问题讨论】:

  • 这很漂亮 - 非标准。你如何定义这种类型的划分?例如,如果你做(2+1j)/(3+0j),你会期待什么?你希望它给你一个复杂的结果还是(0+0j)
  • 出于好奇,在信号处理中何时使用复数?我想不出来的例子。
  • 这很愚蠢。只需使用浮点运算完成工作,并沿途假设所有浮点值。然后您将不会面临类型转换(因为您期望浮动)。我已经为 NumPy 中的工作编写了许多数字信号处理模块,即使在处理特别依赖于高斯整数属性的事物(例如根轨迹工作或一些特殊的拉普拉斯变换)时,这种类型转换也从来不是问题。不是从性能(速度、四舍五入)的角度,也不是从数学的角度。
  • @EMS:我完全理解使用整数进行复杂算术的缺点。但是,您的论点对这个问题不是很有建设性。我只想说我有一个要求,有时需要与格式化为整数的复杂数据进行交互。
  • 只是为了添加到讨论中,我也有复杂整数的要求。它基本上用于对算法的定点实现进行建模。这绝对是罕见的。也就是说,在我的情况下,它可以使用具有适当舍入的浮点复数值来解决(因为我只处理乘法)。

标签: python numpy


【解决方案1】:

我还处理大量复杂的整数数据,通常是基带数据。 我用

dtype = np.dtype([('re', np.int16), ('im', np.int16)])

它并不完美,但它充分描述了数据。我用它来加载到内存中而不会使数据的大小加倍。它还具有能够使用 HDF5 透明地加载和存储的优势。

DATATYPE  H5T_COMPOUND {
    H5T_STD_I16LE "re";
    H5T_STD_I16LE "im";
}

使用起来很简单,只是与众不同。

x = np.zeros((3,3),dtype)
x[0,0]['re'] = 1
x[0,0]['im'] = 2
x
>> array([[(1, 2), (0, 0), (0, 0)],
>>        [(0, 0), (0, 0), (0, 0)],
>>        [(0, 0), (0, 0), (0, 0)]], 
>>  dtype=[('re', '<i2'), ('im', '<i2')])

为了对其进行数学运算,我将其转换为原生复杂浮点类型。显而易见的方法行不通,但也没那么难。

y = x.astype(np.complex64) # doesn't work, only gets the real part
y = x['re'] + 1.j*x['im']  # works, but slow and big
y = x.view(np.int16).astype(np.float32).view(np.complex64)
y
>> array([[ 1.+2.j,  0.+0.j,  0.+0.j],
>>        [ 0.+0.j,  0.+0.j,  0.+0.j],
>>        [ 0.+0.j,  0.+0.j,  0.+0.j]], dtype=complex64)

最后的转换方法灵感来自https://stackoverflow.com/a/5658446/1784179

【讨论】:

  • 我转换我的数组f(看起来像这样:array([(127, -128), (127, 127)], dtype=[('I', 'i1'), ('Q', 'i1')]))像这样:f_complex = [np.complex(*x) for x in f]。它仍然不是一个复杂的整数,但我认为从 int 转换为复杂的 float 的更优雅的解决方案。
  • @StefanD。我预计您的方法会更慢,但我很震惊地在 1M 点上测量 > 10000 倍。它也只适用于一维(而不是任何数组),f_complex 是一个列表,而不是一个数组。
  • 真的很有创意。我想知道您何时执行此操作...当您使用y = x.view(np.int16).astype(np.float32).view(np.complex64) 时是否会发生复制操作,是或否?如果不。这太棒了国际海事组织。
  • astype() 进行类型转换(和复制),但 view() 没有。所以这是一个复制和转换操作。
【解决方案2】:

您是否考虑过使用 [[a,-b],[b,a]] 形式的矩阵来代替复数?矩阵的普通乘法和加法对应于加法和复数的乘法(这个 2x2 矩阵集合的子环与复数同构)。我认为python可以处理整数矩阵代数。

【讨论】:

  • 谢谢。这可能原则上起作用,但主要的动机是提高效率,允许创建现有复杂整数数据的视图。我认为这种方法需要将复杂值预处理为您建议的矩阵形式。
  • @JasonR 好消息是,例如,这将允许 $(23232+54546i)*(25436+123132132i)$ 的精确乘法,而不会因使用浮点数而产生任何不精确的算术。
【解决方案3】:

Python 和 Numpy 确实支持复数,如果你想要复数,只需使用 np.round 或忽略小数部分。

例如

import numpy as np
#Create 100 complex numbers in a 1D array
a=100*np.random.sample(100)+(100*np.random.sample(100)*1j)
#Reshape to a 2D array
np.round(a)
a.reshape(10,10)

#Get the real and imag parts of a couple x/y points as integers
print int(a[1:2].real)
print int(a[3:4].imag)

【讨论】:

  • OP 想要复杂的整数
  • 这就是我想说的,使用复数并将其视为整数。
  • 这适用于许多应用程序。我怀疑那些投反对票的人不明白这个问题。
猜你喜欢
  • 2015-07-14
  • 2021-03-09
  • 1970-01-01
  • 2012-01-03
  • 2011-02-27
  • 1970-01-01
  • 2012-07-10
  • 2019-07-05
  • 2019-11-18
相关资源
最近更新 更多