【问题标题】:Numeric integral of sin(x)/xsin(x)/x 的数值积分
【发布时间】:2018-06-10 15:24:58
【问题描述】:

我想使用 scipy 在 python 中用 sin(x)/x 的积分计算定积分。 n = 256。它似乎效果不佳:

 from scipy import integrate

 exact = integrate.quad(lambda x : (np.sin(x))/x, 0, 2*np.pi)[0]
 print("Exact value of integral:", exact)

 # Approx of sin(x)/x by Trapezoidal rule
 x = np.linspace(0, 2*np.pi, 257)
 f = lambda x : (np.sin(x))/x
 approximation = np.trapz(f(x), x)
 print ("Estimated value of trapezoidal O(h^2):", round(approximation, 5), 
   '+', round((2/256)**2, 5))
 print ("real error:", exact - approximation)

 # Approx of sin(x)/x by Simpsons 1/3 rule
 approximation = integrate.simps(f(x), x)
 print("Estimated value of simpsons O(h^4):", round(approximation, 9), 
   '+', round((2/256)**4, 9))
 print ("real error:", exact - approximation)

 plt.figure()
 plt.plot(x, f(x))
 plt.show()

精确的积分计算得很好,但我得到一个求积错误...怎么了?

Exact value of integral: 1.4181515761326284
Estimated value of trapezoidal O(h^2): nan + 6e-05
real error: nan
Estimated value of simpsons O(h^4): nan + 4e-09
real error: nan

提前致谢!

【问题讨论】:

    标签: python python-3.x numpy scipy integral


    【解决方案1】:

    您的代码中至少存在一些问题:

    1. 您的 linspace0 开始,因此当您评估要积分的函数时,在梯形积分的开头,您有:sin(0)/0 = nan。您应该使用数字零而不是精确零(在下面的示例中,我使用了1e-12
    2. 当您获得第一个 nannan + 1.0 = nan 时:这意味着在您的代码中,当您对区间上的积分求和时,第一个 nan 会弄乱您的所有结果。
    3. 仅适用于 python 2:除法 2/256 是 2 个整数之间的除法,结果为 0。尝试改用2.0/256.0(感谢@MaxU 指出这一点)。

    这是你的代码修复(我在 python2 中运行它,这是我现在使用的 pc 中安装的):

    from scipy import integrate
    import numpy as np
    
    exact = integrate.quad(lambda x : (np.sin(x))/x, 0, 2*np.pi)[0]
    print("Exact value of integral:", exact)
    
    # Approx of sin(x)/x by Trapezoidal rule
    x = np.linspace(1e-12, 2*np.pi, 257) # <- 0 has become a numeric 0
    f = lambda x : (np.sin(x))/x
    approximation = np.trapz(f(x), x)
    print ("Estimated value of trapezoidal O(h^2):", round(approximation, 5), 
      '+', round((2.0/256.0)**2, 5))
    print ("real error:", exact - approximation)
    
    # Approx of sin(x)/x by Simpsons 1/3 rule
    approximation = integrate.simps(f(x), x)
    print("Estimated value of simpsons O(h^4):", round(approximation, 9), 
      '+', round((2/256)**4, 9))
    print ("real error:", exact - approximation)
    

    及其输出:

    ('Exact value of integral:', 1.4181515761326284)
    ('Estimated value of trapezoidal O(h^2):', 1.41816, '+', 6e-05)
    ('real error:', -7.9895502944626884e-06)
    ('Estimated value of simpsons O(h^4):', 1.418151576, '+', 0.0)
    ('real error:', 2.7310242955991271e-10)
    

    Discalimer sin(x)/x -&gt; 1 for x -&gt; 0 的限制,但由于 sin(1e-12)/1e-13 = 1 的浮动舍入!

    【讨论】:

      【解决方案2】:

      您可以让函数返回 1(sin(x)/x 在 0 中的限制)而不是 NaN for x == 0。这样,您不必作弊并更改你整合是为了排除 0。

      import numpy as np
      import matplotlib.pyplot as plt
      from scipy import integrate
      
      exact = integrate.quad(lambda x : (np.sin(x))/x, 0, 2*np.pi)[0]
      print("Exact value of integral:", exact)
      
      
      def f(x):
          out = np.sin(x) / x
          # For x == 0, we get nan. We replace it by the 
          # limit of sin(x)/x in 0
          out[np.isnan(out)] = 1
          return out
      
      # Approx of sin(x)/x by Trapezoidal rule
      
      x = np.linspace(0, 2*np.pi, 257)
      
      approximation = np.trapz(f(x), x)
      print ("Estimated value of trapezoidal O(h^2):", round(approximation, 5), 
        '+', round((2/256)**2, 5))
      print ("real error:", exact - approximation)
       # Approx of sin(x)/x by Simpsons 1/3 rule
      approximation = integrate.simps(f(x), x)
      print("Estimated value of simpsons O(h^4):", round(approximation, 9), 
        '+', round((2/256)**4, 9))
      print ("real error:", exact - approximation)
      plt.figure()
      plt.plot(x, f(x))
      plt.show()
      

      输出:

      Exact value of integral: 1.4181515761326284
      Estimated value of trapezoidal O(h^2): 1.41816 + 6e-05
      real error: -7.98955129322e-06
      Estimated value of simpsons O(h^4): 1.418151576 + 4e-09
      real error: 2.72103006793e-10
      

      【讨论】:

        【解决方案3】:

        NaN 的意思是“非数字”。在您的情况下,基本上是无穷大。创建时:

        x = np.linspace(0, 2*np.pi, 257)
        

        你创建了一个值为0的数组,然后你尝试除以x,但你不能除以0...

        一个解决方案是使用这个:

        x = np.linspace(0.1, 2*np.pi, 257)
        

        给你这个:

        Exact value of integral: 1.4181515761326284
        Estimated value of trapezoidal O(h^2): 1.31822 + 6e-05
        real error: 0.099935104987
        Estimated value of simpsons O(h^4): 1.318207115 + 4e-09
        real error: 0.0999444614012
        

        越接近零,近似值就越好!

        【讨论】:

        • 我想0.0000000000001会更好!
        • 哈哈,没错,但更好的是 Matteo 刚刚对我来说,1e-12,这是 0 之前可能的最小数字!
        【解决方案4】:

        scipy.special.sici 将返回正弦和余弦积分。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-06-29
          • 1970-01-01
          • 2022-06-10
          • 1970-01-01
          • 2018-06-23
          • 1970-01-01
          • 2012-04-25
          相关资源
          最近更新 更多