如何让 SymPy 将 1.0 之类的整数替换为 1

how to get SymPy to replace ints like 1.0 with 1

抱歉新手问题,但到目前为止我还没有在其他地方找到答案。

假设我们有一个符号,我们将它乘以浮点数一:

import sympy

x = sympy.Symbol('x')
x = 1.0 * x

无论我做什么,包含这个 x 的所有表达式也将包含因子一:

from pprint import pprint
pprint(x)
pprint(sympy.simplify(x))

输出:

1.0⋅x
1.0⋅x

在上面的例子中,我想输出x而不是1.0⋅x。是否有可能以用浮点数 1 解决所有乘法的方式简化表达式?我应该将这个浮点数转换为另一种数据类型吗?

看起来是因为 floating-point 与整数 1 - 如果可以不用 1,就不要使用 1.0,也许吧?

您可以检查它是否与 if f.as_integer_ratio() == (1, 1) 相同 1.0,如果是,则不要在前面添加不必要的“1.0”:

>>> xf = 1.0 * x
>>> xi = 1 * x

>>> xf
1.0*x
>>> xi
x

>>> pprint(xf)
1.0*x
>>> pprint(xi)
x

可能是floating-point不准确(我不太了解sympy,不能多说)。

编辑:float.as_integer_ratio() 的运行时间很小,回答你的问题:

>>> python -m timeit -n 1000000 '(1.0).as_integer_ratio() == (1,1)'
1000000 loops, best of 5: 172 nsec per loop

>>> python -m timeit -n 1000000 '(1.1).as_integer_ratio() == (1,1)'
1000000 loops, best of 5: 327 nsec per loop

>>> python -m timeit -n 1000000 '(1.01).as_integer_ratio() == (1,1)'
1000000 loops, best of 5: 331 nsec per loop

>>> python -m timeit -n 1000000 '(0.999999999999).as_integer_ratio() == (1,1)'
1000000 loops, best of 5: 329 nsec per loop

我找到了解决办法。有一个特殊的函数 nsimplify() 可以完成这项工作。

如果 nsimplify 比您预期的更激进——它会将 Floats 简化为 接近 但不完全相同的值——那么您可以考虑以下函数仅针对以浮点数表示的整数。

>>> def flint(eq):
...     """convert floats that are ints to ints"""
...     reps = {}
...     e = eq.replace(
...         lambda x: x.is_Float and x == int(x),
...         lambda x: reps.setdefault(x, Dummy()))
...     return e.xreplace({v: int(k) for k, v in reps.items()})
>>> flint(1.0*x)
x
>>> flint(1.0*x+x**2.0)
x**2 + x