【问题标题】:Ignore imaginary roots in sympy忽略 sympy 中的假想根
【发布时间】:2013-02-19 01:56:38
【问题描述】:

我正在使用 sympy 求解多项式:

x = Symbol('x')
y = solve(int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"]), x)

y 是可能解决方案的列表。但是,我需要忽略想象中的,只使用真正的解决方案。另外,我希望将解决方案作为值而不是表达式。现在它看起来像:

[-2/3 - 55**(1/3)*(-1/2 - sqrt(3)*I/2)/3, -2/3 - 55**(1/3)*(-1/2 + sqrt(3)*I/2)/3, -55**(1/3)/3 - 2/3]

我需要最后一个表达式的值 (-2.22756)。 sympy 中是否有函数可以简化这一点?

【问题讨论】:

  • 如果您只对根的浮点/双精度近似感兴趣,SymPy 很可能不是正确的库。如果您使用 numpy/scipy,您可能会获得更好的性能和更简单的代码。如果你选择 sympy 而不是 numpy/scipy 因为它更小,你可以使用 mpmath 变得更小,它在 sympy 中用于数字(任意精度不受机器限制)

标签: python math sympy


【解决方案1】:

如果您将x 设置为真实,SymPy 只会为您提供真实的解决方案

x = Symbol('x', real=True)
solve(..., x)

【讨论】:

  • 我正在尝试使用这种方法求解一个方程,但它仍然返回虚解
  • 你在用solve吗?请注意,新的solveset 忽略了对符号设置的假设(使用solveset(domain=S.Reals) 在实际域中求解。如果您使用的是求解,这是一个错误,应该是reported
  • 我都尝试了:使用假设求解、求解集和域=S.Reals 的求解集。 Solve 只是跳过了对要求解的变量(作为求解集)在 30 秒内到达解决方案的假设,而具有域的求解集无法在 20 分钟内到达解决方案。会不会是重复的? (github.com/sympy/sympy/issues/9973)
【解决方案2】:

solve()对于各种类型的解决方案没有一致的输出,请使用solveset(Eq,x,domain=S.Reals)

 from sympy import ImageSet, S 
 x = Symbol('x')
 y = solveset(int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2+int(row["scaleC"])*x + int(row["scaleD"]), x, domain=S.Reals)

http://docs.sympy.org/latest/modules/solvers/solveset.html

【讨论】:

    【解决方案3】:

    这正是 real_roots 的用途,尤其适用于系数为整数的情况:

    x = Symbol('x')
    eq = int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"])
    y = real_roots(eq, x)  # gives [CRootOf(...), ...]
    

    CRootOf 实例的值可以评估为您需要的任何精度,并且不应包含任何虚部。例如,

    >>> [i.n(12) for i in real_roots(3*x**3 - 2*x**2 + 7*x - 9, x)]
    [1.07951904858]
    

    注意:我记得,solve 会发回它无法确认满足假设的根(即,如果没有发现它们对于假设是错误的,那么它们会被返回)。此外,如果您想从求解中获得更一致的输出,@PyRick,请设置标志 dict=True

    【讨论】:

      【解决方案4】:

      正如 Krastonov 提到的那样,mpmath 提供了一种更简单的方法:

      y = polyroots([int(row["scaleA"]), int(row["scaleB"]), int(row["scaleC"]), int(row["scaleD"])-value])
      for root in y:
         if "j" not in str(root):
             value = root
      

      【讨论】:

        【解决方案5】:

        我设法简单地忽略了包含字符 "I" 的解决方案,并使用 .evalf() 来评估表达式。现在的代码是:

            x = Symbol('x')
            y = solve(int(row["scaleA"])*x**3 + int(row["scaleB"])*x**2 + int(row["scaleC"])*x + int(row["scaleD"]), x)
            for root in y:
                if "I" not in str(root):
                    print("This One:" + str(root.evalf()))
        

        【讨论】:

        • 过滤掉真正根的更好方法是检查root.is_real
        猜你喜欢
        • 2011-10-03
        • 1970-01-01
        • 2021-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多