昆仑山:眼中无形心中有穴之穴人合一

夫君子之行,静以修身,俭以养德;非澹泊无以明志,非宁静无以致远。夫学须静也,才须学也;非学无以广才,非志无以成学。怠慢则不能励精,险躁则不能冶性。年与时驰,意与岁去,遂成枯落,多不接世。悲守穷庐,将复何及!

 

数值分析之数值积分

import numpy as np


# 线性插值
def linear_interpolation(x_data, y_data, x):
    n = len(x_data)  # 获取数据点的数量
    for i in range(n - 1):  # 遍历每个区间
        if x_data[i] <= x <= x_data[i + 1]:  # 检查 x 是否在当前区间内
            # 计算斜率
            slope = (y_data[i + 1] - y_data[i]) / (x_data[i + 1] - x_data[i])
            # 计算插值结果
            y = y_data[i] + slope * (x - x_data[i])

            # 打印详细计算步骤
            print(f"线性插值计算细节:")
            print(f"使用点: ({x_data[i]}, {y_data[i]}), ({x_data[i + 1]}, {y_data[i + 1]})")
            print(
                f"斜率: (y_data[i+1] - y_data[i]) / (x_data[i+1] - x_data[i]) = ({y_data[i + 1]} - {y_data[i]}) / ({x_data[i + 1]} - {x_data[i]}) = {slope}")
            print(f"结果: y = y_data[i] + 斜率 * (x - x_data[i]) = {y_data[i]} + {slope} * ({x} - {x_data[i]}) = {y}")

            return y  # 返回插值结果
    return None  # 如果 x 不在任何区间内,返回 None


# 二次插值=抛物线插值
def quadratic_interpolation(x_data, y_data, x):
    n = len(x_data)  # 获取数据点的数量
    for i in range(n - 2):  # 遍历每个区间
        if x_data[i] <= x <= x_data[i + 2]:  # 检查 x 是否在当前区间内
            # 使用三个点 (x_data[i], y_data[i]), (x_data[i+1], y_data[i+1]), (x_data[i+2], y_data[i+2]) 进行二次插值
            A = np.array([
                [1, x_data[i], x_data[i] ** 2],
                [1, x_data[i + 1], x_data[i + 1] ** 2],
                [1, x_data[i + 2], x_data[i + 2] ** 2]
            ])  # 构建系数矩阵 A
            B = np.array([y_data[i], y_data[i + 1], y_data[i + 2]])  # 构建常数矩阵 B
            coeffs = np.linalg.solve(A, B)  # 解线性方程组求解系数 a, b, c
            a, b, c = coeffs  # 提取系数 a, b, c

            # 打印详细计算步骤
            print(f"二次插值计算细节:")
            print(
                f"使用点: ({x_data[i]}, {y_data[i]}), ({x_data[i + 1]}, {y_data[i + 1]}), ({x_data[i + 2]}, {y_data[i + 2]})")
            print(f"系数矩阵 A:\n{A}")
            print(f"常数矩阵 B:\n{B}")
            print(f"解得系数 a, b, c: {a}, {b}, {c}")

            y = a + b * x + c * x ** 2  # 计算插值结果
            print(f"结果: y = {a} + {b} * {x} + {c} * {x}^2 = {y}")
            return y  # 返回插值结果
    return None  # 如果 x 不在任何区间内,返回 None


# Lagrange插值
def lagrange_interpolation(x_data, y_data, x):
    n = len(x_data)  # 获取数据点的数量
    y = 0  # 初始化插值结果
    for i in range(n):  # 遍历每个数据点
        l = 1  # 初始化基函数 L_i(x)
        for j in range(n):  # 计算基函数 L_i(x)
            if i != j:
                l *= (x - x_data[j]) / (x_data[i] - x_data[j])  # 计算 L_i(x)
        y += y_data[i] * l  # 累加每个基函数的结果

        # 打印详细计算步骤
        print(f"Lagrange插值计算细节:")
        print(f"使用点: ({x_data[i]}, {y_data[i]})")
        print(f"L_i(x) = {l}")
        print(f"y += y_data[i] * L_i(x) = {y_data[i]} * {l} = {y_data[i] * l}")

    print(f"最终结果: y = {y}")
    return y  # 返回插值结果


# 牛顿法
def divided_difference(x_data, y_data):
    n = len(x_data)  # 获取数据点的数量
    coef = y_data.copy()  # 复制 y_data 作为初始系数
    for j in range(1, n):  # 计算差分系数
        for i in range(n - 1, j - 1, -1):
            coef[i] = (coef[i] - coef[i - 1]) / (x_data[i] - x_data[i - j])  # 更新系数
    return coef  # 返回差分系数


def newton_interpolation(x_data, y_data, x):
    coef = divided_difference(x_data, y_data)  # 获取差分系数
    n = len(x_data)  # 获取数据点的数量
    y = coef[-1]  # 初始化插值结果为最后一个系数
    print(f"牛顿插值计算细节:")
    print(f"初始系数: {coef}")
    for i in range(n - 2, -1, -1):  # 计算插值结果
        y = y * (x - x_data[i]) + coef[i]  # 更新插值结果
        print(f"y = y * (x - x_data[i]) + coef[i] = {y} * ({x} - {x_data[i]}) + {coef[i]} = {y}")
    print(f"最终结果: y = {y}")
    return y  # 返回插值结果


# Hermite插值
def L(x, i):
    l = 1  # 初始化基函数 L_i(x)
    for j in range(len(x_data)):  # 计算基函数 L_i(x)
        if i != j:
            l *= (x - x_data[j]) / (x_data[i] - x_data[j])  # 更新 L_i(x)
    return l  # 返回基函数 L_i(x)


def hermite_interpolation(x_data, y_data, y_prime_data, x):
    n = len(x_data)  # 获取数据点的数量
    H = 0  # 初始化插值结果
    for i in range(n):  # 遍历每个数据点
        L_i = L(x, i)  # 计算基函数 L_i(x)
        h1 = 1 - 2 * L_i * (x - x_data[i])  # 计算 h1
        h2 = (x - x_data[i]) * L_i  # 计算 h2
        H += y_data[i] * h1 * L_i * L_i + y_prime_data[i] * h2 * L_i * L_i  # 累加每个基函数的结果

        # 打印详细计算步骤
        print(f"Hermite插值计算细节:")
        print(f"使用点: ({x_data[i]}, {y_data[i]}), 导数: {y_prime_data[i]}")
        print(f"L_i(x) = {L_i}")
        print(f"h1 = 1 - 2 * L_i * (x - x_data[i]) = 1 - 2 * {L_i} * ({x} - {x_data[i]}) = {h1}")
        print(f"h2 = (x - x_data[i]) * L_i = ({x} - {x_data[i]}) * {L_i} = {h2}")
        print(
            f"H += y_data[i] * h1 * L_i * L_i + y_prime_data[i] * h2 * L_i * L_i = {y_data[i]} * {h1} * {L_i} * {L_i} + {y_prime_data[i]} * {h2} * {L_i} * {L_i} = {H}")

    print(f"最终结果: H = {H}")
    return H  # 返回插值结果


# 分段线性插值
def piecewise_linear_interpolation(x_data, y_data, x):
    n = len(x_data)  # 获取数据点的数量
    for i in range(n - 1):  # 遍历每个区间
        if x_data[i] <= x <= x_data[i + 1]:  # 检查 x 是否在当前区间内
            # 计算斜率
            slope = (y_data[i + 1] - y_data[i]) / (x_data[i + 1] - x_data[i])
            # 计算插值结果
            y = y_data[i] + slope * (x - x_data[i])

            # 打印详细计算步骤
            print(f"分段线性插值计算细节:")
            print(f"使用点: ({x_data[i]}, {y_data[i]}), ({x_data[i + 1]}, {y_data[i + 1]})")
            print(
                f"斜率: (y_data[i+1] - y_data[i]) / (x_data[i+1] - x_data[i]) = ({y_data[i + 1]} - {y_data[i]}) / ({x_data[i + 1]} - {x_data[i]}) = {slope}")
            print(f"结果: y = y_data[i] + 斜率 * (x - x_data[i]) = {y_data[i]} + {slope} * ({x} - {x_data[i]}) = {y}")

            return y  # 返回插值结果
    return None  # 如果 x 不在任何区间内,返回 None


# 三次样条插值
def cubic_spline_interpolation(x_data, y_data, x):
    n = len(x_data)  # 获取数据点的数量
    h = np.diff(x_data)  # 计算相邻数据点之间的差值
    alpha = np.zeros(n - 1)  # 初始化 alpha 数组
    for i in range(1, n - 1):  # 计算 alpha 数组
        alpha[i] = 3.0 / h[i] * (y_data[i + 1] - y_data[i]) - 3.0 / h[i - 1] * (y_data[i] - y_data[i - 1])

    l = np.zeros(n)  # 初始化 l 数组
    mu = np.zeros(n)  # 初始化 mu 数组
    z = np.zeros(n)  # 初始化 z 数组
    l[0] = 2.0 * (h[0] + h[1])  # 计算 l[0]
    mu[0] = h[1] / l[0]  # 计算 mu[0]
    z[0] = alpha[0] / l[0]  # 计算 z[0]
    for i in range(1, n - 1):  # 计算 l, mu, z 数组
        l[i] = 2.0 * (h[i - 1] + h[i]) - h[i - 1] * mu[i - 1]  # 计算 l[i]
        mu[i] = h[i] / l[i]  # 计算 mu[i]
        z[i] = (alpha[i] - h[i - 1] * z[i - 1]) / l[i]  # 计算 z[i]
    l[n - 1] = h[n - 2] * (2.0 - mu[n - 2])  # 计算 l[n-1]
    z[n - 1] = (alpha[n - 2] - h[n - 2] * z[n - 2]) / l[n - 1]  # 计算 z[n-1]
    c = np.zeros(n)  # 初始化 c 数组
    b = np.zeros(n - 1)  # 初始化 b 数组
    d = np.zeros(n - 1)  # 初始化 d 数组
    c[n - 1] = z[n - 1]  # 设置 c[n-1]
    for i in range(n - 2, -1, -1):  # 计算 c, b, d 数组
        c[i] = z[i] - mu[i] * c[i + 1]  # 计算 c[i]
        b[i] = (y_data[i + 1] - y_data[i]) / h[i] - h[i] * (c[i + 1] + 2.0 * c[i]) / 3.0  # 计算 b[i]
        d[i] = (c[i + 1] - c[i]) / (3.0 * h[i])  # 计算 d[i]

    for i in range(n - 1):  # 遍历每个区间
        if x_data[i] <= x <= x_data[i + 1]:  # 检查 x 是否在当前区间内
            dx = x - x_data[i]  # 计算 dx
            # 计算插值结果
            y = y_data[i] + b[i] * dx + c[i] * dx * dx + d[i] * dx * dx * dx

            # 打印详细计算步骤
            print(f"三次样条插值计算细节:")
            print(f"使用区间: [{x_data[i]}, {x_data[i + 1]}]")
            print(f"系数: b[i] = {b[i]}, c[i] = {c[i]}, d[i] = {d[i]}")
            print(
                f"结果: y = y_data[i] + b[i] * dx + c[i] * dx * dx + d[i] * dx * dx * dx = {y_data[i]} + {b[i]} * {dx} + {c[i]} * {dx} * {dx} + {d[i]} * {dx} * {dx} * {dx} = {y}")

            return y  # 返回插值结果
    return None  # 如果 x 不在任何区间内,返回 None


# 示例数据
x_data = np.array([1, 2, 3])  # 定义 x 数据点
y_data = np.array([2, 3, 5])  # 定义 y 数据点
x = 1.5  # 定义需要插值的 x 值
print(f"线性插值法在 x = {x} 处的结果: {linear_interpolation(x_data, y_data, x)}\n")  # 打印线性插值结果

print(f"抛物线插值=二次插值法在 x = {x} 处的结果: {quadratic_interpolation(x_data, y_data, x)}\n")  # 打印二次插值结果

print(f"拉格朗日插值法在 x = {x} 处的结果: {lagrange_interpolation(x_data, y_data, x)}\n")  # 打印拉格朗日插值结果

print(f"牛顿插值法在 x = {x} 处的结果: {newton_interpolation(x_data, y_data, x)}\n")  # 打印牛顿插值结果

print(f"分段线性插值法在 x = {x} 处的结果: {piecewise_linear_interpolation(x_data, y_data, x)}\n")  # 打印分段线性插值结果

print(f"三次样条插值法在 x = {x} 处的结果: {cubic_spline_interpolation(x_data, y_data, x)}\n")  # 打印三次样条插值结果

# 埃尔米特插值法示例数据
x_data1 = np.array([1, 2])  # 定义 x 数据点
y_data1 = np.array([2, 3])  # 定义 y 数据点
y_prime_data1 = np.array([1, 1])  # 定义导数数据点
x = 1.5  # 定义需要插值的 x 值
print(f"埃尔米特插值法在 x = {x} 处的结果: {hermite_interpolation(x_data1, y_data1, y_prime_data1, x)}\n")  # 打印埃尔米特插值结果



posted on 2025-01-16 22:12  Indian_Mysore  阅读(9)  评论(0)    收藏  举报

导航