You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#重积分:包括直角坐标、极坐标下二重积分的计算、直角坐标、柱坐标、球坐标下三重积分的计算等
import unittest
import sympy as sp
from convert_formula import *
import math
def rectangular_double_integration(region1, region2, function, integration_order=('y','x')):
var1, var2 = integration_order
lower1, upper1 = region1 # 直接使用符号表达式(可能包含外层变量)
lower2, upper2 = region2
function = sp.sympify(convert_formula(function))
x, y = sp.symbols('x y')
# 根据积分顺序动态选择积分变量
if var1 == 'y' and var2 == 'x':
integration1 = sp.integrate(function, (y, lower1, upper1)) # 内层积分限可包含x
result = sp.integrate(integration1, (x, lower2, upper2))
elif var1 == 'x' and var2 == 'y':
integration1 = sp.integrate(function, (x, lower1, upper1)) # 内层积分限可包含y
result = sp.integrate(integration1, (y, lower2, upper2))
else:
raise ValueError('积分顺序仅支持("y","x")或("x","y")')
return result
def polar_double_integration(function, rou_region, theta_region, integration_order=('rou','theta')):
var1, var2 = integration_order
function = sp.sympify(convert_formula(function)) * sp.symbols('rou') # 极坐标雅可比行列式
rou, theta = sp.symbols('rou theta')
# 根据顺序动态积分
if var1 == 'rou' and var2 == 'theta':
inner = sp.integrate(function, (rou, *rou_region))
result = sp.integrate(inner, (theta, *theta_region))
elif var1 == 'theta' and var2 == 'rou':
inner = sp.integrate(function, (theta, *theta_region))
result = sp.integrate(inner, (rou, *rou_region))
else:
raise ValueError('积分顺序仅支持("rou","theta")或("theta","rou")')
return result
def rectangular_triple_integration(region1, region2, region3, function, integration_order=('z','y','x')):
var1, var2, var3 = integration_order
function = sp.sympify(convert_formula(function))
x, y, z = sp.symbols('x y z')
# 动态构建积分变量元组
vars = {'x':x, 'y':y, 'z':z}
regions = {var1: region1, var2: region2, var3: region3}
# 按顺序嵌套积分
inner = sp.integrate(function, (vars[var1], *regions[var1]))
middle = sp.integrate(inner, (vars[var2], *regions[var2]))
result = sp.integrate(middle, (vars[var3], *regions[var3]))
return result
def cylindrical_triple_integration(function, z_region, rou_region, theta_region, integration_order=('z','rou','theta')):
var1, var2, var3 = integration_order
function = sp.sympify(convert_formula(function)) * sp.symbols('rou') # 柱坐标雅可比行列式rou
z, rou, theta = sp.symbols('z rou theta')
# 动态映射积分变量与区域
vars = {'z': z, 'rou': rou, 'theta': theta}
regions = {var1: z_region, var2: rou_region, var3: theta_region}
# 按顺序嵌套积分
inner = sp.integrate(function, (vars[var1], *regions[var1]))
middle = sp.integrate(inner, (vars[var2], *regions[var2]))
result = sp.integrate(middle, (vars[var3], *regions[var3]))
return result
def spherical_triple_integration(function, r_region, phi_region, theta_region, integration_order=('r','phi','theta')):
var1, var2, var3 = integration_order
function = sp.sympify(convert_formula(function)) * (sp.symbols('r')**2) * sp.sin(sp.symbols('phi')) # 球坐标雅可比行列式r²sinφ
r, phi, theta = sp.symbols('r phi theta')
# 动态映射积分变量与区域
vars = {'r': r, 'phi': phi, 'theta': theta}
regions = {var1: r_region, var2: phi_region, var3: theta_region}
# 按顺序嵌套积分
inner = sp.integrate(function, (vars[var1], *regions[var1]))
middle = sp.integrate(inner, (vars[var2], *regions[var2]))
result = sp.integrate(middle, (vars[var3], *regions[var3]))
return result
def spherical_triple_integration(rou, theta, gamma, function):
"""
求球坐标下三重积分值
:param rou: ρ的积分区域(以元组或列表形式给出)
:param theta: θ的积分区间(以元组或列表形式给出)
:param gamma: γ的积分区间(以元组或列表形式给出)
:param function: 被积函数(以柱坐标形式给出)
:return: 三重积分值
"""
rou1, rou2 = rou[0], rou[1]
theta1, theta2 = theta[0], theta[1]
gamma1, gamma2 = gamma[0], gamma[1]
function = sp.sympify(convert_formula(function))
rou, theta, gamma = sp.symbols('rou theta gamma')
function = function * rou**2
integration1 = sp.integrate(function, (rou, rou1, rou2))
integration1 = integration1* sp.sin(theta)
integration2 = sp.integrate(integration1, (theta, theta1, theta2))
result = sp.integrate(integration2, (gamma, gamma1, gamma2))
return result
class TestIntegralFunctions(unittest.TestCase):
def test_rectangular_double_integration(self):
"""测试直角坐标系下的二重积分"""
# 测试案例1: ∫∫(x^2 + y^2) dxdy其中 x∈[0,1], y∈[0,1] = 2/3
result = rectangular_double_integration(
region1=(0, 1),
region2=(0, 1),
function="x^2 + y^2"
)
self.assertEqual(float(result), 2/3)
# 测试案例2: ∫∫1 dxdy其中 x∈[0,2], y∈[0,3] = 6
result = rectangular_double_integration(
region1=(0, 3),
region2=(0, 2),
function="1"
)
self.assertEqual(result, 6)
def test_polar_double_integration(self):
"""测试极坐标系下的二重积分"""
# 测试案例1: ∫∫(r) rdrdθ其中 r∈[0,1], θ∈[0,2π] = π
result = polar_double_integration(
function="rou",
rou=(0, 1),
theta=(0, 2*math.pi)
)
self.assertEqual(result, 2*math.pi/3)
# 测试案例2: ∫∫(r^2) rdrdθ其中 r∈[0,2], θ∈[0,π] = 4π
result = polar_double_integration(
function="rou^2",
rou=(0, 2),
theta=(0, math.pi)
)
self.assertEqual(result, 4*math.pi)
def test_rectangular_triple_integration(self):
"""测试直角坐标系下的三重积分"""
# 测试案例1: ∫∫∫(x + y + z) dxdydz其中 x∈[0,1], y∈[0,1], z∈[0,1] = 3/2
result = rectangular_triple_integration(
region1=(0, 1),
region2=(0, 1),
region3=(0, 1),
function="x + y + z"
)
self.assertEqual(float(result), 3/2)
# 测试案例2: ∫∫∫1 dxdydz其中 x∈[0,1], y∈[0,2], z∈[0,3] = 6
result = rectangular_triple_integration(
region1=(0, 3),
region2=(0, 2),
region3=(0, 1),
function="1"
)
self.assertEqual(result, 6)
def test_cylindrical_triple_integration(self):
"""测试柱坐标系下的三重积分"""
# 测试案例1: ∫∫∫(r) r**2dzdrdθ其中 r∈[0,1], θ∈[0,2π], z∈[0,1] = π
result = cylindrical_triple_integration(
rou=(0, 1),
theta=(0, 2*math.pi),
region=(0, 1),
function="rou"
)
self.assertEqual(result, 2*math.pi/3)
# 测试案例2: ∫∫∫(z) rdzdrdθ其中 r∈[0,2], θ∈[0,π], z∈[0,1] = 2π
result = cylindrical_triple_integration(
rou=(0, 2),
theta=(0, math.pi),
region=(0, 1),
function="z"
)
self.assertEqual(result, math.pi)
def test_spherical_triple_integration(self):
"""测试球坐标系下的三重积分"""
# 测试案例1: ∫∫∫(r) r²sin(θ)drdθdφ其中 r∈[0,1], θ∈[0,π], φ∈[0,2π] = π
result = spherical_triple_integration(
rou=(0, 1),
theta=(0, math.pi),
gamma=(0, 2*math.pi),
function="rou"
)
self.assertEqual(result, math.pi)
# 测试案例2: ∫∫∫(1) r²sin(θ)drdθdφ其中 r∈[0,1], θ∈[0,π], φ∈[0,2π] = 4π/3
result = spherical_triple_integration(
rou=(0, 1),
theta=(0, math.pi),
gamma=(0, 2*math.pi),
function="1"
)
self.assertEqual(result, 4*math.pi/3)
def UI():
while True:
command = input('请选择将要进行的操作1.直角坐标下二重积分 2.极坐标下二重积分 3.直角坐标系下三重积分 4.柱坐标下三重积分 5.球坐标下三重积分 6.退出\n(所有积分区间请不要使用半开半闭区间的形式给出,积分顺序由内到外输入,极坐标、柱坐标、球坐标需在原函数上乘的雅戈比行列式已经自动传入,不要重复输入)')
if command=='1':
function = input('请输入被积函数:')
order = input('请输入积分顺序(格式:"y,x""x,y"默认y,x') or 'y,x'
var1, var2 = order.split(',') # 解析积分变量顺序
# 输入符号积分限(支持变量表达式如"x"、"2*y"
lower1 = sp.sympify(convert_formula(input(f'请输入{var1}的下限:')))
upper1 = sp.sympify(convert_formula(input(f'请输入{var1}的上限:')))
lower2 = sp.sympify(convert_formula(input(f'请输入{var2}的下限:')))
upper2 = sp.sympify(convert_formula(input(f'请输入{var2}的上限:')))
print('直角坐标系下二重积分值:', rectangular_double_integration(
region1=(lower1, upper1),
region2=(lower2, upper2),
function=function,
integration_order=tuple(order.split(','))
))
if command=='2':
function = input('请输入极坐标被积函数:')
order = input('请输入积分顺序(格式:"rou,theta""theta,rou"默认rou,theta') or 'rou,theta'
var1, var2 = order.split(',')
# 符号积分限输入
lower1 = sp.sympify(convert_formula(input(f'请输入{var1}的下限:')))
upper1 = sp.sympify(convert_formula(input(f'请输入{var1}的上限:')))
lower2 = sp.sympify(convert_formula(input(f'请输入{var2}的下限:')))
upper2 = sp.sympify(convert_formula(input(f'请输入{var2}的上限:')))
print('极坐标二重积分值:', polar_double_integration(
function=function,
rou_region=(lower1, upper1) if var1=='rou' else (lower2, upper2),
theta_region=(lower2, upper2) if var1=='rou' else (lower1, upper1),
integration_order=tuple(order.split(','))
))
if command=='3':
function = input('请输入被积函数:')
order = input('请输入积分顺序(格式:"z,y,x"或其他排列默认z,y,x') or 'z,y,x'
vars = order.split(',')
# 输入三个符号积分限
regions = [
(sp.sympify(convert_formula(input(f'请输入{vars[0]}的下限:'))),
sp.sympify(convert_formula(input(f'请输入{vars[0]}的上限:'))),),
(sp.sympify(convert_formula(input(f'请输入{vars[1]}的下限:'))),
sp.sympify(convert_formula(input(f'请输入{vars[1]}的上限:'))),),
(sp.sympify(convert_formula(input(f'请输入{vars[2]}的下限:'))),
sp.sympify(convert_formula(input(f'请输入{vars[2]}的上限:'))),)
]
print('直角坐标三重积分值:', rectangular_triple_integration(
function=function,
region1=regions[0],
region2=regions[1],
region3=regions[2],
integration_order=tuple(vars)
))
if command=='4':
function = input('请输入柱坐标被积函数:')
order = input('请输入积分顺序(格式:"z,rou,theta"或其他排列默认z,rou,theta') or 'z,rou,theta'
vars = order.split(',')
# 输入符号积分限(支持变量表达式)
regions = [
(sp.sympify(convert_formula(input(f'请输入{vars[0]}的下限r/phi/theta'))),
sp.sympify(convert_formula(input(f'请输入{vars[0]}的上限r/phi/theta')))),
(sp.sympify(convert_formula(input(f'请输入{vars[1]}的下限r/phi/theta'))),
sp.sympify(convert_formula(input(f'请输入{vars[1]}的上限r/phi/theta')))),
(sp.sympify(convert_formula(input(f'请输入{vars[2]}的下限r/phi/theta'))),
sp.sympify(convert_formula(input(f'请输入{vars[2]}的上限r/phi/theta'))))
]
print('柱坐标三重积分值:', cylindrical_triple_integration(
function=function,
z_region=regions[0] if vars[0]=='z' else next(r for r in regions if vars.index(r[0].name) == 0),
rou_region=regions[1] if vars[1]=='rou' else next(r for r in regions if vars.index(r[1].name) == 1),
theta_region=regions[2] if vars[2]=='theta' else next(r for r in regions if vars.index(r[2].name) == 2),
integration_order=tuple(vars)
))
if command=='5':
function = input('请输入球坐标被积函数使用r,phi,theta')
order = input('请输入积分顺序(格式:"r,phi,theta"或其他排列默认r,phi,theta') or 'r,phi,theta'
vars = order.split(',')
# 输入符号积分限(支持变量表达式)
regions = [
(sp.sympify(convert_formula(input(f'请输入{vars[0]}的下限r/phi/theta'))),
sp.sympify(convert_formula(input(f'请输入{vars[0]}的上限r/phi/theta')))),
(sp.sympify(convert_formula(input(f'请输入{vars[1]}的下限r/phi/theta'))),
sp.sympify(convert_formula(input(f'请输入{vars[1]}的上限r/phi/theta')))),
(sp.sympify(convert_formula(input(f'请输入{vars[2]}的下限r/phi/theta'))),
sp.sympify(convert_formula(input(f'请输入{vars[2]}的上限r/phi/theta'))))
]
print('球坐标三重积分值:', spherical_triple_integration(
function=function,
r_region=regions[0] if vars[0]=='r' else next(r for r in regions if vars.index(r[0].name) == 0),
phi_region=regions[1] if vars[1]=='phi' else next(r for r in regions if vars.index(r[1].name) == 1),
theta_region=regions[2] if vars[2]=='theta' else next(r for r in regions if vars.index(r[2].name) == 2),
integration_order=tuple(vars)
))
if command=='6':
break
if __name__ == "__main__":
UI()
unittest.main(exit=False)