不一致的 numpy 复数乘法结果

Inconsistent numpy complex multiplication results

考虑以下 Python 将两个复数相乘的代码:

import numpy as np
a = np.matrix('28534314.10478439+28534314.10478436j').astype(np.complex128)
b = np.matrix('-1.39818115e+09+1.39818115e+09j').astype(np.complex128)

#Verify values
print(a)
print(b)

c=np.dot(a.getT(),b)

#Verify product
print(c)

现在产品应该是 -7.979228021897728000e+16 + 48j,当我在 Spyder 上 运行 时这是正确的。但是,如果我在 MPI4py 程序上通过 MPI 从发送方接收到值 ab(我验证它们已被正确接收),则产品是错误的,特别是 -7.97922801e+16+28534416.j.在这两种情况下,我都使用 numpy 1.14.3 和 Python 2.7.14。后一种情况的唯一区别是,在接收值之前,我用以下方法初始化矩阵:

a = np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)
b = np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)

然后函数 MPI::Comm::Irecv() 为它们提供正确的值。

如果 ab 正确但 c 错误,在后一种情况下会出现什么问题? numpy 是否任意设置虚部,因为它比产品的实部小得多?

首先,这并没有解决 mp 的问题,但由于它是在评论中提出的:

np.matrix 可以接受一个字符串参数,并从中生成一个数字矩阵。还要注意形状是 (1,1)

In [145]: a = np.matrix('28534314.10478439+28534314.10478436j')
In [146]: a
Out[146]: matrix([[28534314.10478439+28534314.10478436j]])
In [147]: a.dtype
Out[147]: dtype('complex128')

字符串输入 np.array 产生一个字符串:

In [148]: a = np.array('28534314.10478439+28534314.10478436j')
In [149]: a
Out[149]: array('28534314.10478439+28534314.10478436j', dtype='<U36')

但是省略引号,我们得到复数数组,形状为 () (0d):

In [151]: a = np.array(28534314.10478439+28534314.10478436j)
In [152]: a
Out[152]: array(28534314.10478439+28534314.10478436j)
In [153]: a.dtype
Out[153]: dtype('complex128')

以及这些值的乘积:

In [154]: b = np.array(-1.39818115e+09+1.39818115e+09j)
In [155]: a*b       # a.dot(b) same thing
Out[155]: (-7.979228021897728e+16+48j)

不使用 mp,我假设初始化和设置是这样的:

In [179]: x=np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)
In [180]: x[:]=a
In [181]: x
Out[181]: matrix([[28534314.10478439+28534314.10478436j]])
In [182]: y=np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)
In [183]: y[:]=b
In [184]: y
Out[184]: matrix([[-1.39818115e+09+1.39818115e+09j]])
In [185]: x*y
Out[185]: matrix([[-7.97922802e+16+48.j]])

可能值得尝试 np.zeros_like 而不是 np.empty_like。这将确保虚部为 0,而不是随机的。那么如果 mp 过程只是设置实部,你应该得到一些不同的东西。