Python 中涉及分数和浮点数的计算精度损失

Ele*_*l95 0 python math sympy fractions python-3.x

import sympy as sp
from fractions import Fraction

new_matrix_aux = [['X',   'B', 'X1', 'X2', 'X3', 'X4', 'X5', 'U1', 'U2'], 
                  ['X2', 10/3,    0,    1,  2/3,  1/3, -2/3, -1/3,  2/3],  
                  ['X1',  4/3,    1,    0,  2/3, -2/3,  1/3,  2/3, -1/3]]

z_function = "Z = 1 * X1 + 2 * X2 + 3 * X3 + 0 * X4 + 0 * X5 + M * U1 + M * U2"


lista_de_operaciones_zj = []

for j in range(1, len(new_matrix_aux[0])):
    z = z_function
    for i in range(1, len(new_matrix_aux)):
        z = z.replace(new_matrix_aux[i][0], str(new_matrix_aux[i][j]))
    for k in range(1, len(new_matrix_aux[0])):
        z = z.replace(new_matrix_aux[0][k], '0')
    z = z.replace(z[0], z[0] + '_' + new_matrix_aux[0][j])
    lista_de_operaciones_zj.append(z)
    print(f'"{z}"')

variables, resultados = [], []

for operacion in lista_de_operaciones_zj:
    variable = operacion.split("Z_")[1].split(" = ")[0]
    variables.append(variable)
    expression = operacion.split("= ")[1]
    resultado = sp.sympify(expression)
    resultados.append(resultado)

output = [variables, resultados]
print(output)
Run Code Online (Sandbox Code Playgroud)

这是我得到的不正确的输出,由于某种原因,在代码的整个数学过程中,计算值的精度会丢失(特别是在那些涉及分数的运算中,如下所示):

[['B', 'X1', 'X2', 'X3', 'X4', 'X5', 'U1', 'U2'], [8.0000000000000003, 1, 2, 2.000000000000000, 0, -0.9999999999999999, 0, 0.9999999999999999]]
Run Code Online (Sandbox Code Playgroud)

这应该是正确的输出矩阵,在计算过程中没有精度损失。

[['B', 'X1', 'X2', 'X3', 'X4', 'X5', 'U1', 'U2'], [8, 1, 2, 2, 0, -1, 0, 1]]
Run Code Online (Sandbox Code Playgroud)

我认为这个问题是由于 Python 中浮点计算的本质造成的。浮点数在内部以二进制表示,可能会引入较小的舍入误差。

Ste*_*tef 5

您的代码以 开头,但之后您根本from fractions import Fraction不会使用。Fraction

要在 python 中声明 a Fraction,请显式编写该单词:

from fractions import Fraction

x = Fraction(1, 3)  # fraction
y = 1/3             # not a fraction

print('x = {}  {}'.format(x, type(x)))
print('y = {}  {}'.format(y, type(y)))
# x = 1/3  <class 'fractions.Fraction'>
# y = 0.3333333333333333  <class 'float'>
Run Code Online (Sandbox Code Playgroud)

或者,由于您正在使用sympy,因此您可以使用sympy.Rational

import sympy

x = sympy.Rational(1,3)
Run Code Online (Sandbox Code Playgroud)

如果您只需要分数,则使用fractions.Fraction. 但如果您需要 sympy 的更多内容,那么我建议完全坚持使用 sympy 并使用sympy.Rational.