【计算方法】非线性方程和优化

0.WARNINGS

    本文章主要适用于计算方法代码的实现参考,由于本人是python究极小白,为了实验课速成了一些内容,因此会包含较多的暴力解法orz,如有代码错误、可优化的地方欢迎各位大佬指出,感激不尽。

    此外,本人制作本文的目的,主要是懒的将代码保存在本地中,且博客方便个人的复习。

    非线性方程和优化主要包含的内容有:二分法;普通迭代法;牛顿迭代法;弦截法(单点&两点);


1.

用二分法求方程 xlnx = 1 在[0.5 , 4] 的近似根,使函数值误差不超过0.001,或有根区间长度不超过0.001。输出保留3位小数。

import math

a=0.5
b=4

def f(x):
    return x*math.log(x)-1

while 1:
    mid=a / 2 + b / 2
    if math.fabs(f(mid)) < 0.001 or math.fabs(a - b) < 0.001:
        ret = mid
        break
    else:
        if f(mid)*f(a)<=0:
            b=mid
        else:
            a=mid

print("%.3f" % ret)

2.

用迭代法求方程 x= e –x在x=0.5附近的一个根,结果的精度要求0.00001。输出保留4位小数

import math

def f(x):
    return math.e**(-x)

x=0.5

while 1:
    temp=x
    x=f(x)
    if math.fabs(temp-x)<0.00001:
        break

print("%.4f" % x)

3.

用迭代法求函数f(x)=x-lnx-2在区间(2,+∞)内的零点,误差是0.00001,最高迭代次数是500次。输出保留三位小数。

import math

def f(x):
    return math.log(x)+2

x=2
cnt=0
while cnt<=500:
    temp=x
    x=f(x)
    if math.fabs(temp-x)<0.00001:
        break
    else:
        cnt += 1

print("%.3f" % x)

4.

用迭代法求方程3 x2- e x=0在[3,4]区间的一个根,结果的精度要求0.0001。输出保留3位小数

import math

def f(x):
    return math.log(3*x**2)

x=3.5
while x>=3 and x<=4:
    temp=x
    x=f(x)
    if math.fabs(temp-x)<0.00001:
        break

print("%.3f" % x)

5.

输出x^3-x^2-1=0的有根区间,并在该有根区间内通过二分法找到其具有4位有效数字的根。

注意:有根区间的长度为0.1,输出到小数点后1位。

例如:

输出:

3.5(有根区间左端点)

3.6(有根区间右端点)

3.578(根)

(此非该题的正确解,只是示例)

import math

def f(x):
    return pow(x,3)-pow(x,2)-1

# 容易发现f(1)<0 and f(2)>0
i=1
while i<2:
    i+=0.1
    if f(i)>0:
        b=i
        a=i-0.1
        break
print("%.1f" % a)
# (有根区间左端点)
print("%.1f" % b)
# (有根区间右端点)

while 1:
    mid=a/2+b/2
    if math.fabs(f(mid))<0.001 or math.fabs(a-b)<0.001:
        ret=mid
        break
    else:
        if f(mid)*f(a)<=0:
            b=mid
        else:
            a=mid
print("%.3f" % ret)
# (根)

6.

设函数f(x)=sinx-(x/2)2,牛顿法求函数的根。初始值是2.0,误差是0.0001,最高迭代次数是500次。输出保留三位小数。

import math

# 设函数f(x)=sinx-(x/2)2,牛顿法求函数的根。
# 初始值是2.0,误差是0.0001,最高迭代次数是500次。输出保留三位小数。

def f(x):
    return math.sin(x)-(x/2)**2

def f1(x):
    return math.cos(x)-x/2

def fai(x):
    return x-f(x)/f1(x)

cnt=0
e=0.0001
myx=2.0
while cnt<500:
    temp=fai(myx)
    if math.fabs(temp-myx)<e:
        myx=temp
        break
    else:
        myx=temp

print("%.3f" % myx)

7.

用牛顿迭代法求解x2=A的根,要求误差小于0.00001

输入:A

输出:迭代序列值 迭代次数(从初值x0=A开始迭代)迭代值保留5位有效数字

例如:

输入: 7

输出: 4.00000 1

2.87500 2

2.65489 3

2.64577 4

2.64575 5

2.64575 6

import math

# 用牛顿迭代法求解x2=A的根,要求误差小于0.00001

A=float(input())

def fai(x,A):
    return x-(x**2-A)/(2*x)

e=0.00001
myx=A
cnt=int(0)
while 1:
    temp=fai(myx,A)
    if math.fabs(temp-myx)<e:
        myx=temp
        cnt+=1
        break
    else:
        myx=temp
        cnt+=1
        print("%.5f %d" % (myx, cnt))

print("%.5f %d" % (myx,cnt))

8.

对非零实数a,采用牛顿迭代法设计一个不用除法运算求解1/a的计算程序。误差小于10-5   初值x0=0.01

输入:a

输出:迭代序列 (保留5位小数) 迭代次数

例如:

输入:7

输出:

0.01930 1
0.03599 2
0.06292 3
0.09812 4
0.12885 5
0.14148 6
0.14284 7
0.14286 8
0.14286 9

import math
import sys

# 对非零实数a,采用牛顿迭代法设计一个不用除法运算求解1/a的计算程序。
# 误差小于10-5   初值x0=0.01

a=float(input())

if a==0:
    print("a cannot be zero")
    sys.exit()

def f(x,a):
    return 1/x-a

def f1(x,a):
    return -1/(x**2)

def fai(x,a):
    return x-f(x,a)/f1(x,a)

e=0.00001
myx=0.01
cnt=int(0)
# fx=1/x
while 1:
    temp=fai(myx,a)
    if math.fabs(temp-myx)<e:
        myx=temp
        cnt+=1
        break
    else:
        myx=temp
        cnt+=1
        print("%.5f %d" % (myx,cnt))

print("%.5f %d" % (myx,cnt))

9.

在重根数未知情况下,求解非线性方程f(x)=e^(2x)-1-2x-2x^2的误差小于0.0001的根。

输入迭代初始值,输出每次的近似解和迭代次数(空格分隔),近似解保留小数点后5。

例如:

输入:2

输出:

-2.47756 1
-0.26450 2
-0.00996 3
-0.00002 4
0.00000 5

import math
import sys

def f(x):
    return math.e**(2*x)-1-2*x-2*x**2

def f1(x):
    return 2*math.e**(2*x)-2-4*x

def f2(x):
    return 4*math.e**(2*x)-4

def fai(x):
    return x-f1(x)*f(x)/(f1(x)**2-f(x)*f2(x))

e=0.0001
cnt=int(0)
myx=float(input())

while 1:
    temp=fai(myx)
    if math.fabs(temp-myx)<e:
        myx = temp
        cnt += 1
        break
    else:
        myx=temp
        cnt+=1
        print("%.5f %d" % (myx,cnt))

print("%.5f %d" % (myx,cnt))

10.

单点弦截法求f(x)=x-sinx-1在[1,2]区间解,误差为0.0001

           输入格式:

                      a的值  b的值  (a为定点)

           输出格式:

                     根(保留4位小数)迭代次数

                      输入:

                                 1 2

                      输出:

                                 1.9346 12

import math

inp = input().split(' ')
a = float(inp[0])
b = float(inp[1])

e=0.0001
cnt=int(1)

def f(x):
    return x-math.sin(x)-1

def fai(x,x0):
    return x-f(x)/(f(x)-f(x0))*(x-x0)
# x0=a

while 1:
    if math.fabs(b-fai(b,a))<e:
        b+=e
        break
    else:
        b=fai(b,a)
        cnt+=1

print("%.4f %d" % (b,cnt))

11.

用双点弦法求方程 xex-1=0 在x=0.5附近的根。初始两点分别是0.3, 0.8, 最高迭代次数是500次,误差是0.0001。输出后值,并保留三位小数。

import math
# 用双点弦法求方程 xex-1=0 在x=0.5附近的根。初始两点分别是0.3, 0.8,
# 最高迭代次数是500次,误差是0.0001。输出后值,并保留三位小数。

def f(x):
    return x*math.e**x-1

def fai(xk,x):
    return xk-f(xk)/(f(xk)-f(x))*(xk-x)
# xk=b,x=a

e=0.0001
a=0.3
b=0.8
cnt=1
myx=0

while cnt<=500:
    if math.fabs(fai(b,a)-myx)<e:
        myx = fai(b, a)
        # output the latter one?
        break
    else:
        myx=fai(b,a)
        a=b
        b=myx
        cnt+=1

print("%.3f" % myx)

12.

对于f(x)=x3-3x-1用三种方法求解。输入两个初值,x0和x1,其中xo作为牛顿法的初值进行迭代求解,x0为单点弦截的不动点和x1作为初值迭代求解,x0和x1作为双点弦截的不动点迭代求解,误差小于0.00001。输出迭代值和迭代次数,迭代值保留5位有小数。

例如:

输入:

1.5 3

输出:

2.06667 1 (牛顿迭代结果)
1.90088 2
1.87972 3
1.87939 4
1.87939 5
1.66667 1(单点弦截迭代结果)
1.96933 2
1.84938 3
1.89032 4
1.87552 5
1.88077 6
1.87889 7
1.87956 8
1.87932 9
1.87941 10
1.87938 11
1.87939 12
1.87938 13
1.66667 1(双点弦截迭代结果)
1.76613 2
1.90130 3
1.87744 4
1.87935 5
1.87939 6
1.87939 7

import math

inp = input().split(' ')
x0 = float(inp[0])
x1 = float(inp[1])
e=0.00001

def f(x):
    return x**3-3*x-1

def f1(x):
    return 3*x**2-3

def fai(x):
    return x-f(x)/f1(x)

def singlefai(x,x0):
    return x-f(x)/(f(x)-f(x0))*(x-x0)
# x0=a

# Newton
newtoncnt=0
myx=x0
while 1:
    temp=fai(myx)
    if math.fabs(temp-myx)<e:
        myx=temp
        newtoncnt+=1
        break
    else:
        myx=temp
        newtoncnt += 1
        print("%.5f %d" % (myx,newtoncnt))
print("%.5f %d" % (myx,newtoncnt))

# print("single")
# single point
singlecnt=0
b=x1
a=x0
while 1:
    if math.fabs(b-singlefai(b,a))<e:
        b+=e
        singlecnt += 1
        break
    else:
        b=singlefai(b,a)
        singlecnt+=1
        print("%.5f %d" % (b,singlecnt))
print("%.5f %d" % (b,singlecnt))

def doublefai(xk,x):
    return xk-f(xk)/(f(xk)-f(x))*(xk-x)
# xk=b,x=a

# double point
#print("double point")
doublecnt=0
b=x1
a=x0
myx=2 # ? not sure
while 1:
    if math.fabs(doublefai(b,a)-myx)<e:
        myx=doublefai(b,a)
        doublecnt += 1
        break
    else:
        myx=doublefai(b,a)
        a=b
        b=myx
        doublecnt+=1
        print("%.5f %d" % (myx,doublecnt))
print("%.5f %d" % (myx,doublecnt))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MorleyOlsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值