简体   繁体   中英

Cannot add matrices more than 20 times in loop

I'm trying to create a sum of 2x2 matrices in a for loop, but when I loop the summation more than 21 times (when my n > 20, as shown below) it gives me the following error message:

TypeError: ufunc 'add' output (typecode 'O') could not be coerced to provided output parameter (typecode 'd') according to the casting rule ''same_kind''

This is my code:

k = 2
n = 21

A2 = np.matrix('0.5 -0.5; 0.5 0.5')
SumA2 = np.zeros((k,k))

for i in range(0, n+1):
    SumA2 += np.linalg.matrix_power(A2, i)/np.math.factorial(i)

print(A2)
print("\n", SumA2)

I'm suspecting it has something to do with the factorial becoming too big, but should that really be an issue? In Matlab I can loop it 1000 times without issue.

At 21, it switches the array type to object:

In [776]: np.linalg.matrix_power(A2,20)/np.math.factorial(20)
Out[776]: 
matrix([[-4.01398205e-22,  0.00000000e+00],
        [ 0.00000000e+00, -4.01398205e-22]])
In [777]: np.linalg.matrix_power(A2,21)/np.math.factorial(21)
Out[777]: 
matrix([[-9.557100128609015e-24, 9.557100128609015e-24],
        [-9.557100128609015e-24, -9.557100128609015e-24]], dtype=object)

more specifically, it's the factorial that's switched:

In [778]: np.array(np.math.factorial(20))
Out[778]: array(2432902008176640000)
In [779]: np.array(np.math.factorial(21))
Out[779]: array(51090942171709440000, dtype=object)

Python3 is using integers for the factorial . Those can be any length. But at this point the value becomes too large to represent with np.int64 . So it switches to using an object dtype array that holds the long Python integer. That switch propagates to the power calculation.

The error arises when it tries to convert this array to a dtype compatible with SumA2 .

In [782]: SumA2 = np.zeros((k,k))
In [783]: SumA2 += Out[777]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-783-53cbd27f9514> in <module>()
----> 1 SumA2 += Out[777]

TypeError: ufunc 'add' output (typecode 'O') could not be coerced to provided output parameter (typecode 'd') according to the casting rule ''same_kind''
In [784]: SumA2 = np.zeros((k,k), object)
In [785]: SumA2 += Out[777]
In [786]: SumA2
Out[786]: 
array([[-9.557100128609015e-24, 9.557100128609015e-24],
       [-9.557100128609015e-24, -9.557100128609015e-24]], dtype=object)

At 170 it starts having problems converting integer to float

Do a 1/factorial(...) first seems to help. And changing the dtype of A2 to a higher precision float may help:

In [812]: np.linalg.matrix_power(A2.astype('float128'),171)*(1/np.math.factorial(171))
Out[812]: 
matrix([[-1.04145922e-335, -1.04145922e-335],
        [ 1.04145922e-335, -1.04145922e-335]], dtype=float128)

With a 2x2 matrix, this really doesn't make special use of numpy . The repeated power could almost as easily be calculated with lists and 'raw' Python numbers. But even those aren't designed for infinite precision math. Integers can be long, but I don't think Python floats are that flexible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM