如何解决以下使用scipy的代码中的零除错误?

huangapple go评论48阅读模式
英文:

How to resolve zero division error for the following code which uses scipy?

问题

这是我的Python代码:

import numpy as np
from scipy.integrate import quad

a = 0.15

def A(z):
    return -a * z**2

def integrand(x, z, B):
    return np.sqrt(-(2/x)*(3*x*A(x).derivative(n=2) - 3*x*(A(x).derivative(n=1))**2 + 6*A(x).derivative(n=1) + 2*B**4*x**3 + 2*B**2*x))

def Phi(z, B):
    result, _ = quad(integrand, 0, z, args=(z, B))
    return result

phi_values = [Phi(z, 0) for z in range(101)]

我遇到了"ZeroDivisionError: float division by zero"的错误。如何解决这个问题?我尝试使用sympy,但没有成功。

英文:

Here's my python code:

import numpy as np
from scipy.integrate import quad

a = 0.15

def A(z):
    return -a * z**2

def integrand(x, z, B):
    return np.sqrt(-(2/x)*(3*x*A(x).derivative(n=2) - 3*x*(A(x).derivative(n=1))**2 + 6*A(x).derivative(n=1) + 2*B**4*x**3 + 2*B**2*x))

def Phi(z, B):
    result, _ = quad(integrand, 0, z, args=(z, B))
    return result

phi_values = [Phi(z, 0) for z in range(101)]

I am getting a "ZeroDivisionError: float division by zero"

How to resolve this issue?

I tried using sympy but to no avail.

答案1

得分: 1

在修复了其他可能存在的问题并进行了一些猜测后,同时将 epsilon 添加为积分下界,

import numpy as np
from scipy.integrate import quad

a = 0.15

# def A(z: float) -> float:
#     return -a * z**2
A = np.poly1d((-a, 0, 0))
Ad1 = A.deriv(m=1)
Ad2 = A.deriv(m=2)

def integrand(x: float, z: float, B: float) -> float:
    return np.sqrt(
        -(2/x)*(
            3*x*Ad2(x)
            - 3*x*Ad1(x)**2
            + 6*Ad1(x)
            + 2*B**4*x**3
            + 2*B**2*x
        )
    )

def Phi(z: float, B: float):
    epsilon = 1e-6
    result, _ = quad(func=integrand, a=epsilon, b=z, args=(z, B))
    return result

phi_values = [Phi(z, 0) for z in range(101)]
print(np.array(phi_values))
[-2.32379001e-06  2.36195636e+00  4.94106004e+00  7.90800675e+00
  1.13771987e+01  1.54207025e+01  2.00839857e+01  2.53965776e+01
...
  3.40309939e+03  3.47405018e+03  3.54573543e+03  3.61815514e+03
  3.69130933e+03]

但更明智的做法是在积分之前对 x 进行解析分离:

import numpy as np
from numpy.polynomial import Polynomial
from scipy.integrate import quad

a = 0.15

# def A(z: float) -> float:
#     return -a * z**2
A = Polynomial((0, 0, -a))
Ad1 = A.deriv(m=1)
Ad2 = A.deriv(m=2)

# Divide by x prior to integrand
Ad1ox = Ad1 // Polynomial((0, 1))

def integrand(x: float, z: float, B: float) -> float:
    return np.sqrt(
        -2*(
            3*Ad2(x)
            - 3*Ad1(x)**2
            + 6*Ad1ox(x)  # 6/x*Ad1(x)
            + 2*B**4*x**2
            + 2*B**2
        )
    )

def Phi(z: float, B: float):
    result, _ = quad(func=integrand, a=0, b=z, args=(z, B))
    return result

phi_values = [Phi(z, 0) for z in range(101)]
print(np.array(phi_values))

这将产生相同的结果。

英文:

Fixing your other breakage re. derivatives with some wild guessing, and adding an epsilon as your lower integration bound,

import numpy as np
from scipy.integrate import quad

a = 0.15


# def A(z: float) -> float:
#     return -a * z**2
A = np.poly1d((-a, 0, 0))
Ad1 = A.deriv(m=1)
Ad2 = A.deriv(m=2)


def integrand(x: float, z: float, B: float) -> float:
    return np.sqrt(
        -(2/x)*(
            3*x*Ad2(x)
            - 3*x*Ad1(x)**2
            + 6*Ad1(x)
            + 2*B**4*x**3
            + 2*B**2*x
        )
    )


def Phi(z: float, B: float):
    epsilon = 1e-6
    result, _ = quad(func=integrand, a=epsilon, b=z, args=(z, B))
    return result


phi_values = [Phi(z, 0) for z in range(101)]
print(np.array(phi_values))
[-2.32379001e-06  2.36195636e+00  4.94106004e+00  7.90800675e+00
  1.13771987e+01  1.54207025e+01  2.00839857e+01  2.53965776e+01
...
  3.40309939e+03  3.47405018e+03  3.54573543e+03  3.61815514e+03
  3.69130933e+03]

But the saner thing to do is analytically divide out x:

import numpy as np
from numpy.polynomial import Polynomial
from scipy.integrate import quad

a = 0.15


# def A(z: float) -> float:
#     return -a * z**2
A = Polynomial((0, 0, -a))
Ad1 = A.deriv(m=1)
Ad2 = A.deriv(m=2)

# Divide by x prior to integrand
Ad1ox = Ad1 // Polynomial((0, 1))


def integrand(x: float, z: float, B: float) -> float:
    return np.sqrt(
        -2*(
            3*Ad2(x)
            - 3*Ad1(x)**2
            + 6*Ad1ox(x)  # 6/x*Ad1(x)
            + 2*B**4*x**2
            + 2*B**2
        )
    )


def Phi(z: float, B: float):
    result, _ = quad(func=integrand, a=0, b=z, args=(z, B))
    return result


phi_values = [Phi(z, 0) for z in range(101)]
print(np.array(phi_values))

which yields the same results.

huangapple
  • 本文由 发表于 2023年3月31日 22:08:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75899485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定