【问题标题】:How to use numpy arrays with fractions?如何使用带有分数的numpy数组?
【发布时间】:2017-07-23 12:02:11
【问题描述】:

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

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

我想要

array([[2/3,    1. ],
       [-2.,   -1. ]])

似乎 numpy 总是切换到浮点数

【问题讨论】:

  • 如果您想使用精确有理数矩阵,sympy 可能会更好。
  • 感谢您的回答,但我不会使用 sympy,因为我已经使用 numpy 开始了我的代码。我不知道 sympy,所以我在下一个代码中记住了这一点!
  • 我在矩阵上测试了 sympy,它非常非常慢:stackoverflow.com/questions/45796747/…

标签: python arrays numpy fractions


【解决方案1】:

由于Fractions 不是native NumPy dtype,要将Fraction 存储在NumPy 数组中,您需要将convert the arrayobject 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)

打印

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

PS。作为user2357112 suggests,如果你想使用有理数,你最好使用sympy。或者,仅将矩阵表示为列表列表。如果您的数组是 object dtype,则使用 NumPy 没有速度优势。

import sympy as sy

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

打印

[[2/3, 1.0], [-2.0, -1.0]]

【讨论】:

  • 谢谢你的回答,转换数组正是我需要的。
【解决方案2】:

您还可以通过在算术运算下滥用 numpy 数组的元素转换,将整个数组转换为 Fraction 对象的 object 数组。 (注意:这要求原始数组是整数数组,因为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)

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

【讨论】:

  • 没有别的办法了吗?我尝试使用.astype,但失败了。我们不能以某种方式直接转换数组吗?这个 hack 很棒,而且很有效。
  • @Param 我假设您的意思是您尝试过A.astype(Fraction)?如果是这样,那么你是对的,因为 numpy 没有与 python 的内置 Fraction 类型相媲美的 dtype。
  • 一个更明确的方法,如果你需要,可以做类似np.vectorize(Fraction)(A)的事情:这将在数组的每个元素上调用Fraction并返回结果。这也会自动将结果数组转换为对象类型数组。 (但我听说np.vectorize 并不总是特别高效......)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-26
  • 2013-10-01
  • 2019-05-18
  • 2013-12-08
  • 2012-03-18
  • 2020-01-12
  • 1970-01-01
相关资源
最近更新 更多