|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
|
3.1 基本语法
|
|
|
1.a=1.234567,b=0.000321保留小数点后3位输出a 指数形式输出 b
|
|
|
|
|
|
print('a=%.3f,b=%.2e' %(a,b))
|
|
|
|
|
|
2.硬盘的存储容量为500GB,该硬盘最多可存放多少个字节的数据量
|
|
|
500*1024*3
|
|
|
|
|
|
3.逆序数输出
|
|
|
输入不小于 100 且小于 1000同时包括小数点后一位的一个浮点数
|
|
|
例如输入:123.4
|
|
|
输出:4.321
|
|
|
|
|
|
x=eval(input())
|
|
|
y=str(x)[::-1]
|
|
|
print(y)
|
|
|
|
|
|
4.对角线求点的个数
|
|
|
对于一个 n 个顶点的凸多边形,它的任何三条对角线都不会交于一点。
|
|
|
请求出图形中对角线交点的个数,以整数输出结果
|
|
|
|
|
|
n=eval(input())
|
|
|
print(int((n*(n-1)*(n-2)*(n-3))/24))
|
|
|
|
|
|
|
|
|
3.2 函数
|
|
|
1.定义一个判断是否是三角形的函数IsTriange(a,b,c),
|
|
|
其中a,b,c为三角形三条边,如果是返回1,否则返回0
|
|
|
|
|
|
from math import *
|
|
|
def IsTriange(a,b,c):
|
|
|
t1=(a+b)>c and (a+c)>b and (b+c)>a
|
|
|
t2=(a-c)<b and (a-b)<c and (b-c)<a
|
|
|
if ( t1 and t2):
|
|
|
return 1
|
|
|
else:
|
|
|
return 0
|
|
|
|
|
|
2.定义一个计算三角形的面积的函数,TriArea(a,b,c),
|
|
|
如果构成三角形,返回三角形的面积,否则返回0
|
|
|
def TriArea(a=3,b=4,c=5):#设置默认参数
|
|
|
if IsTriange(a,b,c):
|
|
|
p=0.5*(a+b+c)
|
|
|
S=(p*(p-a)*(p-b)*(p-c))**0.5
|
|
|
else:
|
|
|
S=0
|
|
|
return S
|
|
|
|
|
|
3.定义一个计算银行本息函数
|
|
|
def moneyrate1(pays,rate,year):
|
|
|
|
|
|
# 根据参数值计算存款本息值
|
|
|
# :param pays:本金
|
|
|
# :param rate:利率
|
|
|
# :param year:年份
|
|
|
# :return: 本息和
|
|
|
|
|
|
print(f"{year}年的本息和为%.4f" %(pays*(1+rate)**year))
|
|
|
|
|
|
4.定义一个判断一个数是否是素数的函数,如果是输出1,否则输出0
|
|
|
|
|
|
def isprime(x):
|
|
|
if x == 1 or x==0:
|
|
|
return 0
|
|
|
for i in range(2,x//2+1):
|
|
|
if x%i == 0:
|
|
|
return 0
|
|
|
return 1
|
|
|
|
|
|
调用isprime()函数求两位数内的绝对素数并输出
|
|
|
|
|
|
for num in range(1,100):
|
|
|
if isprime(num) == 1:
|
|
|
num1=(num%10)*10+num//10
|
|
|
if isprime(num1) == 1:
|
|
|
print(f'{num}和{num1}是绝对素数')
|
|
|
|
|
|
5.验证哥德巴赫猜想,即:任何一个大于或等于6的偶数,
|
|
|
可以表示成两个素数之和。例如:11111112 = 11 + 11111101
|
|
|
定义函数Goldbach(N)将整数N分解成两素数之和以验证哥德巴赫猜想
|
|
|
def Goldbach(N): # 将N分解成两素数之和
|
|
|
if N < 6 or N % 2 == 1: # 若N小于6或N为奇数
|
|
|
print('N应该是大于等于6的偶数')
|
|
|
else:
|
|
|
# 循环判断,得到符合要求的小于N的两个素数,并打印
|
|
|
for x in range(2, N //2 + 1): #为什么是从2到N/2
|
|
|
# 调用isPrime函数得到符合要求的小于N的两个素数
|
|
|
if isprime(x)==1 and isprime(N - x)==1:
|
|
|
print(N, '=', x, '+', N - x)
|
|
|
break
|
|
|
|
|
|
6.信用卡号是否合法的判断规则为:
|
|
|
a对给定的8位信用卡号码,如43589795,
|
|
|
从最右边数字开始,隔一位取一个数相加,如5+7+8+3=23。
|
|
|
b将未出现在第一步中的数字乘2,然后将相乘的结果的每位数字相加
|
|
|
例如 未出现在第一步中的数字乘2后分别为(从右至左)
|
|
|
18、18、10、8则将所有数字相加为1+8+1+8+1+0+8=27。
|
|
|
c将上述两步得到的数字相加,得数个位为0则输入的信用卡号是有效的
|
|
|
|
|
|
def validCreditCard(num):
|
|
|
a,b= 0,0
|
|
|
num1,num2 = num,num//10
|
|
|
for i in range(4):
|
|
|
a = a + num1%10
|
|
|
num1 = num1//100
|
|
|
for i in range(4):
|
|
|
b = b+((num2%10*2)%10+(num2%10*2)//10)
|
|
|
num2 = num2//100
|
|
|
if (a+b)%10==0:
|
|
|
valid = True
|
|
|
else:
|
|
|
valid = False
|
|
|
return valid
|
|
|
|
|
|
7.打印日历 3.2 第6关
|
|
|
|
|
|
3.3 条件分支
|
|
|
1.判断某一年是否是闰年,是则输出yes,否则输出no
|
|
|
def isyear(year):
|
|
|
if year%400==0:
|
|
|
return 1
|
|
|
elif year%4==0 and year%100!=0:
|
|
|
return 1
|
|
|
else:
|
|
|
return 0
|
|
|
|
|
|
2.对给定的三个整数,按从小到大排序
|
|
|
def sortThree(num1,num2,num3):
|
|
|
max1=max(num1,num2,num3)
|
|
|
min1=min(num1,num2,num3)
|
|
|
sum1=sum(num1,num2,num3)
|
|
|
mid1=sum1-max1-min1
|
|
|
return min1,mid1,max1
|
|
|
|
|
|
|
|
|
3.4 循环
|
|
|
1.从键盘输入m行n列,在屏幕上输出m行n列的*行图案
|
|
|
|
|
|
m,n= eval(input())
|
|
|
for i in range(m):
|
|
|
for x in range(n):
|
|
|
print('*',end='')
|
|
|
print() #换行
|
|
|
|
|
|
2.从键盘输入m行,在屏幕上输出m行的直角图案
|
|
|
|
|
|
m=eval(input())
|
|
|
for i in range(1,m+1):
|
|
|
for j in range(1,2*i):
|
|
|
print('*',end='')
|
|
|
print()
|
|
|
|
|
|
3.从键盘输入m行,在屏幕上输出m行的等腰三角形图案
|
|
|
|
|
|
m=eval(input())
|
|
|
for i in range(1,m+1):
|
|
|
for x in range(1,m+1-i):
|
|
|
print(' ',end='')
|
|
|
for j in range(1,2*i):
|
|
|
print('*',end='')
|
|
|
print()
|
|
|
|
|
|
4.在数学上,斐波那契数列以如下被以递推的方法定义:
|
|
|
F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)
|
|
|
斐波那契 请完成求第n项斐波那契数的程序并输出结果
|
|
|
|
|
|
def fibNumber(n) :
|
|
|
F1=1
|
|
|
F2=1
|
|
|
if n%2==0:
|
|
|
n=n/2
|
|
|
flag=2
|
|
|
else:
|
|
|
n=(n+1)/2
|
|
|
flag=1
|
|
|
for i in range(int(n-1)):
|
|
|
r1=F1+F2
|
|
|
r2=r1+F2
|
|
|
F1=r1
|
|
|
F2=r2
|
|
|
if flag==1:
|
|
|
return F1
|
|
|
else:
|
|
|
return F2
|
|
|
|
|
|
5.从键盘接收两个整数,求出这两个整数的最大公约数和最小公倍数
|
|
|
|
|
|
#定义一个求两个数的最大公约数的函数
|
|
|
def gcd(a,b):
|
|
|
A = max(a,b)
|
|
|
B = min(a,b)
|
|
|
if A%B == 0:
|
|
|
ys = B
|
|
|
else:
|
|
|
while B>0:
|
|
|
a =A
|
|
|
b =B
|
|
|
A = B
|
|
|
B = a % b
|
|
|
if B == 0:
|
|
|
ys = A
|
|
|
return ys
|
|
|
m,n = eval(input())
|
|
|
gcdnum=gcd(m,n)
|
|
|
print("最大公约数:%d"% gcdnum)
|
|
|
print("最小公倍数:%d"%((m*n)/gcdnum))
|
|
|
|
|
|
6.求:1-3!+5!-7!......(-1)n-1(2n-1)!,求前n的项的和
|
|
|
|
|
|
def nj(a):
|
|
|
b=1
|
|
|
for i in range(1,a+1):
|
|
|
b=b*i
|
|
|
return b
|
|
|
def sumSequ(n):
|
|
|
s=0
|
|
|
a,flag=1,1
|
|
|
for i in range(n):
|
|
|
s=s+nj(a)*flag
|
|
|
flag=-flag
|
|
|
a+=2
|
|
|
return s
|
|
|
|
|
|
7. 第5关:循环综合-天天向上的力量
|
|
|
|
|
|
|
|
|
3.5 字符串基本操作
|
|
|
1.输出songs中出现最多的一个中文字,并输出该字出现次数
|
|
|
如果有多个字出现次数相同,请以原文本中最先出现的那个为准。
|
|
|
|
|
|
#创建空字典
|
|
|
dic={}
|
|
|
#删去空格
|
|
|
songsnsp=songs.replace(' ','')
|
|
|
for word in songsnsp:
|
|
|
#判断字典中是否存在该键
|
|
|
if word in dic.keys():
|
|
|
dic[word]+=1
|
|
|
else:
|
|
|
dic[word]=1
|
|
|
pyout=max(dic,key=dic.get)
|
|
|
pot=dic[pyout]
|
|
|
print(pyout,pot)
|
|
|
|
|
|
2.将歌曲以最长的那一行为标准,其它行居中对齐左补句号输出
|
|
|
|
|
|
songs=input() #仅含空格和中文的歌词字符串
|
|
|
将songs按空格分割成一个字符串列表
|
|
|
tmpso=songs.split()
|
|
|
|
|
|
#2. 以上面的字符串列表为基础,找出最长的那一个字符串,
|
|
|
以它为长度基准,其它字符串居中对齐左补中文句号。按行输出整首歌曲
|
|
|
#对齐公式:(最长行的长度-当前行的长度)//2为左补句号数
|
|
|
|
|
|
longest=0 #最长的字符串的长度
|
|
|
for lis in tmpso:
|
|
|
if len(lis)>longest:
|
|
|
longest=len(lis)
|
|
|
else:
|
|
|
pass
|
|
|
|
|
|
pyout=''
|
|
|
for li in tmpso:
|
|
|
l=len(li)
|
|
|
addnum=(longest-l)//2
|
|
|
py='。'*addnum+str(li)
|
|
|
if pyout=='':
|
|
|
pyout=pyout+py
|
|
|
else:
|
|
|
pyout=pyout+'\n'+py
|
|
|
|
|
|
print(pyout)
|
|
|
|
|
|
|
|
|
4.1 列表
|
|
|
1.第4关:嵌套列表 矩阵相关
|
|
|
|
|
|
2.在屏幕上输出杨辉三角形图形
|
|
|
|
|
|
def print_(l):
|
|
|
for i in l:
|
|
|
print(i)
|
|
|
|
|
|
num = eval(input()) #num为杨辉三角的行数
|
|
|
s=[[1],[1,1]]
|
|
|
l=[1,1]
|
|
|
for i in range(1,num-1):
|
|
|
for j in range(0,i):
|
|
|
a=s[i][j]+s[i][j+1]
|
|
|
l.insert(1,a)
|
|
|
a=0
|
|
|
s.append(l)
|
|
|
l=[1,1]
|
|
|
a=0
|
|
|
print_(s)
|
|
|
|
|
|
3.约瑟夫问题 n个人按1,2,3,… ,n编号,并顺序围坐一圈。
|
|
|
开始按照1,2,3,… ,m 报数,凡报到 m 的出列,直到所有人出列为止
|
|
|
|
|
|
n,m=eval(input())
|
|
|
result=[] #出圈列表
|
|
|
p=[]
|
|
|
for i in range(1,n+1):
|
|
|
p.append(i)
|
|
|
p=p*2*n
|
|
|
for j in range(n):
|
|
|
for i in range(m):
|
|
|
a=p.pop(0)
|
|
|
result.append(a)
|
|
|
while a in p:
|
|
|
p.remove(a)
|
|
|
print("出圈列表:")
|
|
|
print(result)
|
|
|
|
|
|
4.2 字典
|
|
|
1统计每个单词的个数(列表或字典的方法) #英文词频统计
|
|
|
for i in WordList:
|
|
|
if i in word_dict.keys():
|
|
|
word_dict[i]+=1
|
|
|
else:
|
|
|
word_dict[i]=1
|
|
|
|
|
|
字典排序,返回值是一个列表
|
|
|
lst=list(word_dict.items())
|
|
|
lst.sort(key=lambda d: d[1],reverse=True)
|
|
|
2.输出最高频率单词和次数 ,多个相同高频字也要输出
|
|
|
for i in lst:
|
|
|
a=lst[0][1]
|
|
|
if i[1]!=a:
|
|
|
break
|
|
|
print('%s %s' %i)
|
|
|
|
|
|
3.编写一个能将3位数以内的整数翻译成英文的程序
|
|
|
|
|
|
dic1={0: '', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine'}
|
|
|
dic2={0:'',10: 'ten', 11: 'eleven', 12:' twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen'}
|
|
|
dic3={0:'',2: 'twenty', 3: 'thirty', 4: 'forty', 5: 'fifty', 6: 'sixty', 7: 'seventy', 8: 'eighty', 9: 'ninety'}
|
|
|
#数字翻译成英文程序
|
|
|
def unit_to_word(u):
|
|
|
将0~9的数字转换成英文,并返回转换后的英文
|
|
|
if u<10:
|
|
|
return dic1[u]
|
|
|
|
|
|
def tens_to_word(t): #利用unit_to_word,将10~19、
|
|
|
以及20~99的十位部分数字转换成英文,并返回转换后的英文
|
|
|
if 10<=t<=19:
|
|
|
return dic2[t]
|
|
|
elif t>=20:
|
|
|
u=t%10
|
|
|
return dic3[t//10]+' '+unit_to_word(u)
|
|
|
|
|
|
def hundreds_to_word(h):
|
|
|
if h==0:
|
|
|
return 'zero'
|
|
|
if h>=100:
|
|
|
u=h//100
|
|
|
a=unit_to_word(u)
|
|
|
b=tens_to_word(h-100*u)
|
|
|
u=h%10
|
|
|
return a+' hundred and '+b
|
|
|
elif h>=10:
|
|
|
b=tens_to_word(h)
|
|
|
return b
|
|
|
else:
|
|
|
return unit_to_word(h)
|
|
|
|
|
|
文件操作
|
|
|
1.路径操作
|
|
|
|
|
|
文件操作账单处理
|
|
|
1.编写一个能读取包含月账单数据的文件信息,输出本月总计情况。
|
|
|
从键盘录入月份值n,读取文件"n月账单.txt",
|
|
|
统计该月总消费金额,并保留2位小数输出
|
|
|
|
|
|
s=0
|
|
|
n=input()
|
|
|
f=open(f'{n}月账单.txt','r',encoding='utf-8')
|
|
|
lines=f.readlines()
|
|
|
for i in lines:
|
|
|
i=i.split()
|
|
|
i.pop(0)
|
|
|
i.append(i.pop().strip('\n'))
|
|
|
s+=sum(map(float,i))
|
|
|
print('本月总消费%.2f元'%s)
|
|
|
f.close()
|
|
|
|
|
|
2.从键盘录入月份值n,读取文件"n月账单.txt",
|
|
|
输出该月本月消费最大的那一天及其消费额(保留2位小数输出)
|
|
|
|
|
|
s=[]
|
|
|
name=[]
|
|
|
n=input()
|
|
|
f=open(f'{n}月账单.txt','r',encoding='utf-8')
|
|
|
lines=f.readlines()
|
|
|
for i in lines:
|
|
|
i=i.split()
|
|
|
name.append(i.pop(0))
|
|
|
i.append(i.pop().strip('\n'))
|
|
|
s.append(sum(map(float,i)))
|
|
|
print(f'消费额最高的是{name[s.index(max(s))]},消费%.2f元'%max(s))
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
数据分析
|
|
|
1.输出前3行学生的平均分列表,控制小数点后两位
|
|
|
|
|
|
print(df['平均分'].round(2).head(3).tolist())
|
|
|
[89.17, 89.83, 85.83]
|
|
|
|
|
|
2.添加平均分列:考勤、实验操作、实验报告的平均
|
|
|
df['平均分']=(df['考勤']+df['实验操作']+df['实验报告'])/3
|
|
|
|
|
|
输出前3行学生的平均分列表,控制小数点后两位
|
|
|
print(df['平均分'].round(2).head(3).tolist())
|
|
|
|
|
|
输出学生人数和班级数
|
|
|
print(df['学号'].count())
|
|
|
print(df['班级名称'].nunique())
|
|
|
|
|
|
分别输出实验报告中值、最高分、最低分
|
|
|
print(df['实验报告'].median())
|
|
|
print(df['实验报告'].max())
|
|
|
print(df['实验报告'].min())
|
|
|
|
|
|
输出实验报告分最低的3位同学的姓名列表
|
|
|
l=df.sort_values(by='实验报告',ascending=True)
|
|
|
['姓名'].head(4).tolist()
|
|
|
l.remove('杨看看')
|
|
|
print(str(l).replace(',',''))
|
|
|
|
|
|
3.输出综合分最高的同学的姓名和学号(可能有多位同学)
|
|
|
print(df.loc[df['综合分']==df['综合分'].max(),
|
|
|
['姓名','学号']])
|
|
|
|
|
|
输出性别为“男”而且实验报告>90的同学的姓名和综合分信息
|
|
|
print(df.loc[(df['性别']=='男')&(df['实验报告']>90),
|
|
|
['姓名','综合分']])
|
|
|
|
|
|
4.按性别统计综合分均值,绘制条图,保存到图片文件filename
|
|
|
def draw_bar(filename):
|
|
|
plt.figure('fig1')
|
|
|
############begin############
|
|
|
x=[1,2]
|
|
|
y=[df.loc[df['性别']=='女','实验报告'].mean(),
|
|
|
df.loc[df['性别']=='男','实验报告'].mean()]
|
|
|
colors=['red','green']
|
|
|
plt.bar(x, y,width=0.8,color=colors)
|
|
|
plt.xticks(x,['女','男'])
|
|
|
plt.title('不同性别的实验报告平均成绩')
|
|
|
plt.ylabel('成绩')
|
|
|
plt.xlabel('性别')
|
|
|
for i,j in zip(x,y):
|
|
|
plt.text(i,j,'%.2f'%j,ha='center',va='bottom')
|
|
|
plt.savefig(filename)
|
|
|
plt.show()
|
|
|
|
|
|
5.统计男女比例,绘制饼图,保存到图片文件filename
|
|
|
def draw_pie(filename):
|
|
|
plt.figure('fig2')
|
|
|
labels = ['女','男']
|
|
|
sizes = [df[df['性别']=='女']['学号'].count(),
|
|
|
df[df['性别']=='男']['学号'].count()]
|
|
|
plt.pie(sizes,labels=labels,autopct='%1.2f%%')
|
|
|
plt.savefig(filename)
|
|
|
|
|
|
6.按班级统计各成绩均值,绘制折线图,保存到图片文件filename
|
|
|
def draw_line(filename):
|
|
|
plt.figure('fig3')
|
|
|
m=df[df['班级名称']=='班级1']
|
|
|
[['考勤','实验操作','实验报告','综合分']].mean()
|
|
|
n=df[df['班级名称']=='班级2']
|
|
|
[['考勤','实验操作','实验报告','综合分']].mean()
|
|
|
plt.plot(m.index,m.values,label='一班',marker="*")
|
|
|
plt.plot(n.index,n.values,label='二班',marker='d')
|
|
|
plt.legend()
|
|
|
plt.xticks(range(4),['考勤','实验操作','实验报告','综合分'])
|
|
|
plt.savefig(filename)
|
|
|
|
|
|
数值预测
|
|
|
1.将第一列和最后一列的元素值乘以2
|
|
|
arr[:,0]=arr[:,0]*2
|
|
|
arr[:,-1]=arr[:,-1]*2
|
|
|
|
|
|
将数组中的零值以及负值全部替换为-5
|
|
|
arr[arr<=0]=-5
|
|
|
|
|
|
2.第2关:模型建立、训练及评估
|
|
|
|
|
|
3.第3关:模型效果可视化
|
|
|
|
|
|
|
|
|
数据分类
|
|
|
第1关:数据可视化
|
|
|
|
|
|
第2关:归一化/标准化
|
|
|
|
|
|
第3关:模型建立、训练与评估
|
|
|
|
|
|
|
|
|
第四章-算法思维-4.3.1方程求根(多种方法求根)
|
|
|
1.用暴力搜索法求方程的近似根
|
|
|
|
|
|
x=eval(input('请输入根的初值:'))
|
|
|
h=eval(input('请输入搜索步长:'))
|
|
|
err=1e-6 #精度,要保证|f(x)|<err
|
|
|
def f(x):
|
|
|
fx=x**3-x-1
|
|
|
return fx
|
|
|
n=0
|
|
|
fx=f(x)
|
|
|
while abs(fx)>=err:
|
|
|
n+=1
|
|
|
fx=f(x)
|
|
|
x=x+h
|
|
|
if fx >= err:
|
|
|
break
|
|
|
if fx >= err:
|
|
|
print('root=False')
|
|
|
print(f'迭代次数:{n-1}')
|
|
|
else:
|
|
|
print('root=%.4f' % x)
|
|
|
print(f'迭代次数:{n-1}')
|
|
|
|
|
|
2.用二分法求方程的近似根
|
|
|
|
|
|
from math import *
|
|
|
a=eval(input('输入根的左边界:'))
|
|
|
b=eval(input('输入根的右边界:'))
|
|
|
err=1e-6
|
|
|
x=1
|
|
|
fx=1
|
|
|
n=0
|
|
|
def f(x):
|
|
|
fx=x**3-x-1
|
|
|
return fx
|
|
|
if f(a)*f(b)>0:
|
|
|
print('root=False')
|
|
|
print('迭代次数:0')
|
|
|
else:
|
|
|
while fabs(fx)>=err:
|
|
|
n+=1
|
|
|
x=(a+b)/2
|
|
|
fx=f(x)
|
|
|
if f(x)*f(a)>0:
|
|
|
a=x
|
|
|
else:
|
|
|
b=x
|
|
|
print('root=%.6f' % x)
|
|
|
print(f'迭代次数:{n}')
|
|
|
|
|
|
3.用牛顿迭代法求方程的近似根
|
|
|
x=eval(input('请输入根的初始值:'))
|
|
|
err=1e-6
|
|
|
n=0
|
|
|
def f(x):
|
|
|
return x**3-x-1
|
|
|
def df(x):
|
|
|
return 3*x **2-1
|
|
|
|
|
|
while True:
|
|
|
if abs(f(x))<err:
|
|
|
print('root=%.6f' % x)
|
|
|
print(f'迭代次数={n}')
|
|
|
break
|
|
|
x=x-f(x)/df(x)
|
|
|
n+=1
|
|
|
|
|
|
4.用牛顿割线法求方程的近似根
|
|
|
x0=eval(input('请输入根的左边界:')) #该输入作为第0个初始根
|
|
|
x1=eval(input('请输入根的右边界:')) #该输入作为第1个初始根
|
|
|
err=1e-6
|
|
|
n=0
|
|
|
def f(x):
|
|
|
return x**3-x-1
|
|
|
if f(x0)==f(x1):
|
|
|
print('root=False')
|
|
|
print('迭代次数=0')
|
|
|
else:
|
|
|
while abs(f(x0))>=err:
|
|
|
x=x1-f(x1)*(x1-x0)/(f(x1)-f(x0))
|
|
|
x0=x1
|
|
|
x1=x
|
|
|
n+=1
|
|
|
print('root=%.6f' % x)
|
|
|
print(f'迭代次数={n-1}')
|
|
|
|
|
|
|
|
|
第四章-算法思维-4.3.2函数求最值(梯度下降法)
|
|
|
1.用梯度下降法求一元函数的最小值
|
|
|
|
|
|
from math import *
|
|
|
x=eval(input('请输入x的初值:'))
|
|
|
lr=eval(input('请输入学习率:'))#学习率,也相当于设置的步长
|
|
|
precision=1e-6#设置收敛精度,f'(x)与0值的差异
|
|
|
max_iters=10000#最大迭代次数
|
|
|
def f(x):
|
|
|
return -sin((1/10)*x)-x**(1/3)
|
|
|
def df(x):
|
|
|
return -(1/10)*cos((1/10)*x)-(1/3)*x**-(2/3)
|
|
|
dfx=df(x)
|
|
|
n=0
|
|
|
while ((n< max_iters) and (abs(dfx)>=precision)):
|
|
|
x=x-lr*dfx
|
|
|
dfx=df(x)
|
|
|
n+=1
|
|
|
if n==10000:
|
|
|
print('False')
|
|
|
else:
|
|
|
print('x=%.6f' % x)
|
|
|
print('最小值=%.6f' % f(x))
|
|
|
print(f'迭代次数={n}')
|
|
|
|
|
|
2.用梯度下降法求二元函数的最值
|
|
|
|
|
|
def f(x,y):
|
|
|
return x**3-y**3+3*x*x+3*y*y-9*x
|
|
|
def dx(x,y):
|
|
|
return 3*x*x+6*x-9
|
|
|
def dy(x,y):
|
|
|
return -y*3*y+6*y
|
|
|
for t in range(max_iters):
|
|
|
if abs(dx(x,y))<err and abs(dy(x,y))<err:
|
|
|
print("迭代次数%d,x=%.8f,y=%.8f,f(x,y)=%.8f"
|
|
|
%(t,x,y,f(x,y)))
|
|
|
break
|
|
|
x=x-lr*dx(x,y)
|
|
|
y=y-lr*dy(x,y)
|
|
|
else:
|
|
|
print('False')
|
|
|
|
|
|
数据拟合(梯度下降法)
|
|
|
1.对给定的100个数据点,用线性拟合的方式求出隐含线性函数
|
|
|
y=ax+b,以保留6位小数的方式输出a,b值,以及均方误差值
|
|
|
注意:在用梯度下降法迭代公式进行迭代更新时,
|
|
|
先更新a的值,再更新b的值
|
|
|
|
|
|
import numpy as np
|
|
|
import pandas as pd
|
|
|
XY=pd.read_csv('XY1.csv')#样本点文件
|
|
|
X=XY.x#样本点的x坐标值
|
|
|
Y=XY.y#样本点的y坐标值
|
|
|
lr=eval(input('请输入学习率:'))
|
|
|
rounds=eval(input('请输入对数据集学习的轮数:'))
|
|
|
seed1,seed2=eval(input('请输入随机数种子:'))
|
|
|
np.random.seed(seed1)
|
|
|
a=np.random.randn()#拟合函数f(x)=ax+b中a的初始值
|
|
|
np.random.seed(seed2)
|
|
|
b=np.random.randn()#拟合函数f(x)=ax+b中b的初始值
|
|
|
|
|
|
def errorCompute(a,b):
|
|
|
error=0
|
|
|
for j in range(len(X)):
|
|
|
error+=1/2*(a*X[j]+b-Y[j])**2
|
|
|
return error/len(X)
|
|
|
for i in range(rounds):
|
|
|
for j in range(len(X)):
|
|
|
gradA=(a*X[j]+b-Y[j])*X[j]; gradB=a*X[j]+b-Y[j]
|
|
|
a=a-lr*gradA; b=b-lr*gradB
|
|
|
print('a=%.6f,b=%.6f,MSE=%.6f'%(a,b,errorCompute(a,b)))
|
|
|
|
|
|
|
|
|
2.对给定的100个数据点,用一元二次函数拟合求出隐含非线性函数
|
|
|
y=cx**2+bx+a,以保留6位小数的方式输出a,b,c值,以及均方误差值
|
|
|
注意:请先求出误差函数分别对a,b,c的偏导值,然后再进行迭代更新
|
|
|
|
|
|
import numpy as np
|
|
|
import pandas as pd
|
|
|
seed1,seed2,seed3=eval(input('请输入随机种子:'))
|
|
|
learning_rate=eval(input('请输入学习率:'))
|
|
|
roundN=eval(input('请输入对数据集学习的轮数:'))
|
|
|
XY=pd.read_csv('XY2.csv')#数据文件,存放样本点,包含x,y值
|
|
|
X=XY.x
|
|
|
Y=XY.y
|
|
|
np.random.seed(seed1)
|
|
|
a=np.random.randn()#函数y=f(x)=cx**2+bx+a中a的初始值
|
|
|
np.random.seed(seed2)
|
|
|
b=np.random.randn()#函数y=f(x)=cx**2+bx+a中b的初始值
|
|
|
np.random.seed(seed3)
|
|
|
c=np.random.randn()#函数y=f(x)=cx**2+bx+a中c的初始值
|
|
|
|
|
|
def errorCompute(a,b,c):
|
|
|
error=0
|
|
|
for j in range(len(X)):
|
|
|
error+=1/2*(c*X[j]*X[j]+b*X[j]+a-Y[j])**2
|
|
|
return error/len(X)
|
|
|
for i in range(roundN):
|
|
|
for j in range(len(X)):
|
|
|
gradA=c*X[j]*X[j]+b*X[j]+a-Y[j];
|
|
|
gradB=(c*X[j]*X[j]+b*X[j]+a-Y[j])*X[j];
|
|
|
gradC=(c*X[j]*X[j]+b*X[j]+a-Y[j])*X[j]*X[j]
|
|
|
a=a-learning_rate*gradA;
|
|
|
b=b-learning_rate*gradB ;c=c-learning_rate*gradC
|
|
|
print('a=%.6f,b=%.6f,c=%.6f,MSE=%.6f'
|
|
|
%(a,b,c,errorCompute(a,b,c)))
|
|
|
|
|
|
|
|
|
"""
|
|
|
|