How to use numpy arrays with fractions?

2019-07-18 11:14发布

I'm trying to implement the simplex method in Python so I need to use the Gaussian elimination on arrays. Very often fractions come up and for more clarity and precision I would like to keep the fractional form instead of using floats. I know the 'fractions' module but I'm struggling to use it. I wrote my code using this module but the arrays are always returned with floats. Isn't it possible to print an array with fractions inside ? On this basic example :

>>> A
array([[-1.,  1.],
   [-2., -1.]])
>>> A[0][0]=Fraction(2,3)
>>> A
array([[ 0.66666667,  1.        ],
   [-2.        , -1.        ]])

I would like to have array([[ 2/3, 1. ], [-2. , -1. ]])

It seems numpy always switches to floats

2条回答
冷血范
2楼-- · 2019-07-18 11:41

You can also convert the entire array to an object array of Fraction objects, by abusing the element-wise conversion of numpy arrays under arithmetic operations. (Note: this requires the original array to be an integer array, since arithmetic between floats and Fractions produce floats.)

>>> A = np.array([[-1,  1],[-2, -1]])
array([[-1,  1],
       [-2, -1]])
>>>
>>> A.dtype
dtype('int64')
>>>
>>> A = A + Fraction()
>>> A
array([[Fraction(-1, 1), Fraction(1, 1)],
       [Fraction(-2, 1), Fraction(-1, 1)]], dtype=object)

With the array in this format, any further arithmetic performed will be over elements of type Fraction.

查看更多
乱世女痞
3楼-- · 2019-07-18 11:50

Since Fractions are not a native NumPy dtype, to store a Fraction in a NumPy array you need to convert the array to object dtype:

import numpy as np
from fractions import Fraction

A = np.array([[-1.,  1.],
              [-2., -1.]])   # <-- creates an array with a floating-point dtype (float32 or float64 depending on your OS)
A = A.astype('object')
A[0, 0] = Fraction(2,3)
print(A)

prints

[[Fraction(2, 3) 1.0]
 [-2.0 -1.0]]

PS. As user2357112 suggests, you might be better off using sympy if you wish to use rational numbers. Or, just represent the matrix as a list of lists. There are no speed advantages to using NumPy if your arrays are of object dtype.

import sympy as sy

A = [[-1.,  1.],
     [-2., -1.]]
A[0][0] = sy.Rational('2/3')
print(A)

prints

[[2/3, 1.0], [-2.0, -1.0]]
查看更多
登录 后发表回答