非线性方程的解法1-3, 1-4

一. 不动点迭代法

【问题描述】在[a,b]区间内寻找方程x**5-2*x-1=0的根的初始近似值位置,确定不动点迭代的初始点(可能有多个),然后使用不动点迭代法求方程的根(可能有多个根)。前后两次迭代的差的绝对值小于delta后停止迭代。

【输入形式】在屏幕上输入3个数,依次为区间左端点值a、右端点值b和所求根的精度值。各数间都以一个空格分隔。根据输入的所求根的精度值可求得delta.

【输出形式】每一行输出一个根(精确到小数点后3位)

【样例1输入】

-1.2 1.5 3

【样例1输出】

-1.000

-0.519

1.291

【样例1说明】输入:左端点a值为-1.2,右端点b值为1.5,前后两次迭代的差的绝对值小于delta=10**(-3)后停止迭代。输出:从小到大顺序输出三个根的值。

【评分标准】根据输入得到的输出准确

import numpy as np
# 求x的函数值,函数为f(x) = x**5 -2*x -1
def f(x):
    y = x ** 5 - 2 * x - 1
    return y
# 确定根的初始近似值
def approot(x, epsilon):
    y = f(x)
    y_range =np.max(y) - np.min(y)
    epsilon2 = y_range * epsilon
    x = np.append(x, x[-1])
    y = np.append(y, y[-1])
    #初始化r为空的array
    r = np.array([], dtype=np.double)
    for k in range(1, x.size-1):
        if y[k-1]*y[k]<=0:
           r = np.append(r, (x[k-1]+x[k])/2)
        s =(y[k]-y[k-1])*(y[k+1]-y[k])
        if np.abs(y[k])<epsilon2 and (s<=0):
           r = np.append(r, x[k])
    return r

def g1(x):
    value = pow(abs(x * 2 + 1), 1 / 5)
    if x < 0:
       value = -value
    return value
def g2(x):
    value = (x ** 5 - 1) / 2
    return value

def fix_point(x0, delta, max_iter, k):
     epsilon = np.finfo(np.float32).eps
     #根序列
     r_seq = np.zeros(max_iter, dtype=np.double)
     r_seq[0] = x0
     #初始化
     r = 0
     n = 0
     err = 0
     for n in range(1, max_iter):
         if k == 0 or k == 2:
             r_seq[n] = g1(r_seq[n-1])
         else:
             r_seq[n] = g2(r_seq[n-1])
         err = np.abs(r_seq[n] - r_seq[n - 1])
         rel_err = err/np.abs(r_seq[n] + epsilon)
         r = r_seq[n]
         if(err < delta)or(rel_err < delta):
             break
     return r, n, err

def main():
        # 创建一个初始值的列表
        arr = input().split()
        arr = np.array(arr, dtype = float)
        #求根的近似值位置
        a = arr[0]
        b = arr[1]
        #在区间[a, b]内取多个点
        #np.linspace创建等差数列
        x = np.linspace(a, b, 9)
        #epsilon是公差
        epsilon = 0.01
        # 有几个根,就有几个近似位置
        r_app = approot(x, epsilon)
        #if r_app is not None: print(r_app)# 输出近似位置
        # 对初始值进行迭代求根
        delta = 0.5 * 10 ** (-int(arr[2]))#精度
        max_iter = 50 #最大迭代次数
        r = np.zeros(r_app.size, dtype=np.double)
        for k in range(r_app.size):
            r[k],_,_ = fix_point(r_app[k], delta, max_iter, k)
            print("%.3f" %r[k])
if __name__ == '__main__':
    main() 

二 . 牛顿法解投射问题

【题目简述】牛顿法解投射体问题(非线性方程求解)

【问题描述】在考虑空气阻力情况下,求解投射体撞击地面时经过的时间和水平飞行行程,其中:y=f(t)=9600*(1-e**(-t/15.0)) - 480t;x=r(t)=2400(1-e**(-t/15.0))。

【输入形式】在屏幕上输入3个数,分别表示起始值、前后两次迭代的差的绝对值精度和f(t)函数值的精度。各数间都以一个空格分隔。

【输出形式】第一行输出投射体撞击地面时经过的时间,第二行输出水平飞行行程,精确到小数点后5位。

【样例1输入】

8 1 1

【样例1输出】

9.08955

1090.69211

【样例1说明】输入:起始值为8、前后两次迭代的差的绝对值精度为0.1和f(t)函数值的精度为0.1。输出:第一行输出投射体撞击地面时经过的时间为9.08955秒,第二行输出水平飞行行程为1090.69211ft。

import numpy as np
import math
def f(t):
    #return 垂直行程
    #e = 2.71828
    y = 9600*(1-math.e**(-t/15.0)) - 480*t
    return y
def r(t):
    # return 水平行程
    #e = 2.71828
    x=2400*(1-math.e**(-t/15.0))
    return x
def ff(t):
    #return f(t)一阶导数的值
    yy = 640*math.e**(-t/15.0)-480
    return yy
def newton(p0, delta, eps, max_iter):
    for k in range(max_iter):
        p1 = p0 - f(p0)/ff(p0)
        err = np.abs(p1-p0)
        rel_err = 2*err/(np.abs(p1)+delta)
        p0 = p1
        if(err<delta or np.abs(f(p0)) <eps or rel_err < delta):
            break
    x= r(p0)
    return p0,x
    """
    y=1
    rel=1
    err =1
    while(err>=delta and abs(y) >=eps and rel >= delta ):
        p1 = p0-f(p0)/ff(p0)
        err = abs(p1 - p0);
        rel = 2*err/(abs(p1)+delta)
        y=f(p0)-f(p1)
        p0 = p1
        #y = f(p0)
        x= r(p0)
    return p0,x
    """
def main():
    p0, n, m = input().split()
    #起始值, 前后两次迭代的差的绝对值精度, f(t)函数值的精度
    p0= float(p0)
    n = int(n)
    m = int(m)
    delta=10 ** (-n) #前后两次迭代的差的绝对值精度
    eps=10 ** (-m) #f(t)函数值的精度
    max_iter = 50
    ans,x = newton(p0, delta, eps, max_iter)
    print("%.5f" % ans) #时间
    print("%.5f" % x) #水平距离
if __name__ == '__main__':
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值