【问题标题】:How makes all low values in the symbolic calculation become zero?如何使符号计算中的所有低值都变为零?
【发布时间】:2019-09-13 02:54:32
【问题描述】:

如何将 SymPy 表达式中的所有低值设为零?比如我的结果是:

1.0*a1*cos(q1) - 6.12e-17*(a2*sin(q2) + a3*sin(q2 + q3) + a4*sin(q2 + q3 + q4))*sin(q1) + 1.0*(a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)

我想将第二个任期(以6.12e-17 开头)更改为零。

【问题讨论】:

  • 如果你通过调用 evalf 得到这个表达式,那么你可以在调用 evalf 时使用 Chop=True:(cos(2)**2+sin(2)**2-1.0).evalf(chop=True)

标签: python sympy


【解决方案1】:

执行此操作的直接方法是将此类数字替换为 0。幼稚的 eq.subs(small, 0) 将失败,因为您输入的 small 不太可能与数字完全相同。但是eq.atoms(Float) 会给你一组这样的数字:

>>> eq.xreplace(dict([(n,0) for n in eq.atoms(Float) if abs(n) < 1e-12]))
1.0*a1*cos(q1) + (1.0*a2*cos(q2) + 1.0*a3*cos(q2 + q3) + 1.0*a4*cos(q2 + q3 + q4))*cos(q1)

【讨论】:

    【解决方案2】:

    可能有更有效的方法(我不熟悉那个库),但我尝试使用regex。如果e- 存在于等式的一部分中,则将其替换为 0(如果需要,可以直接删除)。但为了能够做到这一点,我必须删除括号内 +- 运算符之间的空格,这样我就可以通过从其他 +- 运算符中拆分来创建一个列表。

    import re
    result='''1.0*a1*cos(q1) - 6.12e-17*(a2*sin(q2) + a3*sin(q2+q3) 
    + a4*sin(q2+q3+q4))sin(q1) + 1.0(a2*cos(q2) 
    + a3*cos(q2+q3) + a4*cos(q2+q3+q4))*cos(q1)'''
    too_small='e-'
    
    mylist=re.split(r"\s+", result)
    
    for i in range(len(mylist)):
        if too_small in mylist[i]:
            mylist[i]='0'
    
    new_result=''.join(mylist)
    print(new_result)
    

    这是输出:

    1.0*a1*cos(q1)-0+a3*sin(q2+q3)+a4*sin(q2+q3+q4))sin(q1)+1.0(a2*cos(q2)+a3*cos(q2+q3)+a4*cos(q2+q3+q4))*cos(q1)
    

    正如我所说,可能有比这更好的方法。

    【讨论】:

      【解决方案3】:

      更多细节呢?我猜你想替换符号计算字符串的一部分,Python中的正则表达式可能会有所帮助,你可以这样编码:

      In [1]: import re
      
      In [2]: s = '1.0*a1*cos(q1) - 6.12e-17*(a2*sin(q2) + a3*sin(q2 + q3) + ' \
         ...:     'a4*sin(q2 + q3 + q4))sin(q1) + 1.0(a2*cos(q2) + ' \
         ...:     'a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)'
      
      In [3]: s = re.sub(r'[+-/*/]\s\S*e-[1-9]\d+\S*\s', '', s)
      
      In [4]: s
      Out[4]: '1.0*a1*cos(q1) + a3*sin(q2 + q3) + a4*sin(q2 + q3 + q4))sin(q1) + 1.0(a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)'
      

      re.sub() 函数的第一个参数决定你想减少什么,e-[1-9]\d+ 代表一个低于 e-10 的数字,你可以修改它,希望对你有帮助。

      【讨论】:

        【解决方案4】:

        带有rational=True 参数的SymPy 的nsimplify 函数将表达式中的浮点数转换为有理数(在给定的容差范围内)。如果低于阈值,6.12e-17 之类的东西将被转换为 0。所以,在你的情况下:

        from sympy import sin, cos, symbols, nsimplify
        
        a1, a2, a3, a4 = symbols("a1, a2, a3, a4")
        q1, q2, q3, q4 = symbols("q1, q2, q3, q4")
        
        expr = (
              1.0*a1*cos(q1)
            - 6.12e-17*(a2*sin(q2) + a3*sin(q2 + q3) + a4*sin(q2 + q3 + q4))*sin(q1)
            + 1.0*(a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)
            )
        
        nsimplify(expr,tolerance=1e-10,rational=True)
        # a1*cos(q1) + (a2*cos(q2) + a3*cos(q2 + q3) + a4*cos(q2 + q3 + q4))*cos(q1)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-01
          • 2022-01-15
          • 2019-09-18
          相关资源
          最近更新 更多