如何使用带分数的 numpy 数组?

Jke*_*kev 10 python arrays numpy fractions

我正在尝试在 Python 中实现单纯形方法,因此我需要对数组使用高斯消元法。分数经常出现,为了更清晰和精确,我想保留分数形式而不是使用浮点数。我知道“分数”模块,但我很难使用它。我使用这个模块编写了我的代码,但数组总是用浮点数返回。是不是可以打印一个里面有分数的数组?在这个基本示例中:

>>> A
array([[-1.,  1.],
   [-2., -1.]])
>>> A[0][0]=Fraction(2,3)
>>> A
array([[ 0.66666667,  1.        ],
   [-2.        , -1.        ]])
Run Code Online (Sandbox Code Playgroud)

我想拥有 array([[ 2/3, 1. ], [-2. , -1. ]])

似乎 numpy 总是切换到浮点数

unu*_*tbu 6

由于Fractions 不是本机 NumPy dtype,要将 a 存储Fraction在 NumPy 数组中,您需要将数组转换objectdtype

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)
Run Code Online (Sandbox Code Playgroud)

印刷

[[Fraction(2, 3) 1.0]
 [-2.0 -1.0]]
Run Code Online (Sandbox Code Playgroud)

附注。正如user2357112 建议的那样sympy如果您希望使用有理数,最好使用。或者,只需将矩阵表示为列表列表。如果您的数组是 dtype,则使用 NumPy 没有速度优势object

import sympy as sy

A = [[-1.,  1.],
     [-2., -1.]]
A[0][0] = sy.Rational('2/3')
print(A)
Run Code Online (Sandbox Code Playgroud)

印刷

[[2/3, 1.0], [-2.0, -1.0]]
Run Code Online (Sandbox Code Playgroud)


Cre*_*oat 6

您还可以通过在算术运算下滥用 numpy 数组的元素转换,将整个数组转换objectFraction对象数组。(注意:这要求原始数组是一个整数数组,因为floats 和Fractions产生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)
Run Code Online (Sandbox Code Playgroud)

对于这种格式的数组,执行的任何进一步算术都将针对类型为 的元素Fraction