Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use numpy arrays with fractions?

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

like image 211
Jkev Avatar asked Mar 03 '17 11:03

Jkev


People also ask

How do you find the Fraction of a NumPy array?

vectorize(Fraction)(A) : this will call Fraction on each element of the array and return the result. This also automatically converts the result array to an object-typed array.

How do you use fractions in Python?

We can convert an integer, a floating point number or a string to a fraction in python . To convert a ratio of two integers to fraction, we use Fraction() method of fractions module and pass the numerator as the first argument and the denominator as the second argument.

How do you convert a Fraction to a float in Python?

Convert a fraction to a floating-point number: float() You can convert Fraction to a floating-point number with float() . The result of an operation between Fraction and float is automatically converted to float .


2 Answers

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.

like image 67
CrepeGoat Avatar answered Oct 02 '22 23:10

CrepeGoat


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]]
like image 30
unutbu Avatar answered Oct 02 '22 23:10

unutbu