目录
实验三:MATLAB软件程序设计
练习一
1.下面给出一些特殊的自然数,请读者编程完成相应的任务:
(1)水仙花数 若一个三位自然数的各位数字的立方和等于该数本身,则称该自然数为水仙花数,例如,153=1^3+5^3+3^3,所以153就是一个水仙花数,编程计算小于1000的所有水仙花数;
clc;clear;
for i=100:999
if mod(i,10)^3+mod(fix(i/10),10)^3+(fix(i/100))^3==i
disp(i)
end
end
(2)回文数 若一个自然数从左边读和从右边读的结果是一模一样的,例如12321,则称该自然数为回文数.对于一个自然数,若将各位数字倒序排出,加到原来的数字上,重复有限次后,若能得到一个回文数,则称该自然数能产生回文数或者对称数,例如:195重复4次就可以产生一个回文数 9339,因为
195+591=786
786+687=1473
1473+3741=5214
5214+4125=9339
通过编程计算,你能找出多少个重复6次能产生回文数的数?又能找出多少个不能产生回文数的数?
function hw=hw(x)
xx=str2num(num2str(x')');
k=0;
for i=length(xx):-1:1
k=k*10+xx(i);
end
hw=k+x;
clc;
for i=1:100
t=i;
for k=1:6
t=hw(t);
end
m=str2num(num2str(t')');
if(m==flip(m))
disp(i);
end
end
在运行时要把function一部分单独创建文件运行,不能像c语言一样在一个项目中运行,并把文件名称与函数名称保持一致,并放在一个文件夹内。(其实也是可以写在一起的,不过需要放在代码后面,并加上end。)
这里我找的是1到100的回文数,可以修改范围来调整寻找区间。
(3)完美数 对于一个自然数而言,若它的真因子之和小于数本身,则称该数为盈数;若它的真因子之和大于数本身,则称该数为亏数;若它的真因子之和等于数本身,则称该数为完美数(完全数)例如:12是亏数,14是盈数,6为完美数。通过编程计算,你能找出多少个完美数?
首先我们要明白什么是真因子:除了本身的因子叫真因子。(这个定义有所争议,有人认为是除了1和本身。但按照题意来看,6是完美数,那么这里所定义的真因子就是第一种)
clc;
sum=0;
for i=1:100
for k=1:i-1
if mod(i,k)==0
sum=sum+k;
end
end
if sum==i
disp(i);
end
sum=0;
end
(4)亲和数 亲和数又称友好数,是指两个自然数中任意一个自然数的真因数之和等于另一个数,例如:220与284就是一对亲和数。通过编程计算,你能找出几对亲和数?(令人惊讶的一个事实是:第二对最小的亲和数(1184,1210)曾经是意大利的一个16岁的男孩帕格尼尼(Paganini )在19世已后期发现的。)
clc;
sum=0;sum1=0;count=0;
for i=1:2000
for k=1:i-1
if mod(i,k)==0
sum=sum+k;
end
end
for f=1:sum-1
if mod(sum,f)==0
sum1=sum1+f;
end
end
if sum1==i&&i<sum
fprintf('%i %i\n',i,sum);
end
sum=0;
sum1=0;
end
我取的范围为1到2000。
2.验证“哥德巴赫(Goldboech )猜想”,即:任何一个大于等于6的正偶数均可表示为两个素数的和要求编写程序,输入一个正偶数,返回两个素数的和.
x=input('请输入一个大于等于6的正整数:');
for i=2:x
for k=2:i
while mod(i,k)~=0
k=k+1;
end
end
if k==i
m=k;
t=2;
while mod(x-m,t)~=0
t=t+1;
end
if t==x-m
fprintf('%i %i',m,x-m);
return;
end
end
end
3.每门课程考试阅卷完毕,任课教师都要对各班的考试成绩进行统计,统计内容包括:全班人数,总得分,平均得分60分以下60-70分70-80分、80-90分及90分以上的人数请编写程序解决这一问题,并自给一组数据验证程序的正确性要求:用户在提示下通过键盘输入学生成绩,计算机自动处理后,显示需要的结果。
clc;clear;count1=0;count2=0;count3=0;count4=0;count5=0;
X=input('请输入全班人的成绩:');
num=length(X);
fprintf('全班人数为:%i\n总得分为:%i\n平均得分为:%.3f\n',num,sum(X),mean(X));
for i=1:num
if X(i)<60
count1=count1+1;
end
if X(i)>=60&&X(i)<70
count2=count2+1;
end
if X(i)>=70&&X(i)<80
count3=count3+1;
end
if X(i)>=80&&X(i)<90
count4=count4+1;
end
if X(i)>=90
count5=count5+1;
end
end
fprintf('60分以下人数为:%i\n60~70分人数为:%i\n70~80分人数为:%i\n80~90分人数为:%i\n90分以上人数为:%i',count1,count2,count3,count4,count5);
示例:请输入全班人的成绩:[78 89 99 96 95 78 56 63]
全班人数为:8
总得分为:654
平均得分为:81.750
60分以下人数为:1
60~70分人数为:1
70~80分人数为:2
80~90分人数为:1
90分以上人数为:3
4. 编写程序实现猜数游戏首先由计算机随机产生一个[1,100]之间的一个整数,然后由用户猜测所产生的这个数根据用户猜测的情况给出不同的提示,如果猜测的数大于产生的数,则显示“High”,小于则显示”Low”,等于则显示“You win !”,同时退出游戏,用户最多有7次机会 。
clc;
clear;
x=randi([1,100]);
m=input('请猜测生成的数:');t=1;
while m~=x&&t<7
if x<m
fprintf('High!\n');
else
fprintf('Low!\n');
end
m=input('请猜测生成的数:');
t=t+1;
end
if t<7&&m==x
fprintf('You win!');
else
fprintf('Sorry, you are really unlucky!')
end
这个程序在运行时发生了一些小事故,一直让你输入,即使你输入的数正确后也让你输入,后来查询了一下才发现,while的end没有和while对齐,只能说这个MATLAB太不人性化了,都隔行打了end了但是没有对齐竟然不好好运行,doge。
5.现在星座学说越来越流行,请你编写程序,要求用户利用交互界面从键盘输入出生月日,根据提供的星座资料,计算机输出对应的星座。
附:各星座对应日期
白羊座:3/21—4/20 金牛座:4/21-5/20 双子座:5/21—6/21 狮子座:7/23-8/22处女座:8/23—9/22 天蝎座:10/23—11/21 射手座:11/22—12/21 巨蟹座:6/22-7/22 天秤座:9/23-10/22 摩羯座:12/22-1/20 水瓶座:1/21—2/18 双鱼座:2/19—3/20
s=struct('zuo',{'白羊座','金牛座','双子座','巨蟹座','狮子座','处女座','天秤座','天蝎座','射手座','摩羯座','水瓶座','双鱼座'},'first',{3.21,4.21,5.21,6.22,7.23,8.23,9.23,10.23,11.22,12.22,1.21,2.19},'last',{4.20,5.20,6.21,7.22,8.22,9.22,10.22,11.21,12.21,1.20,2.18,3.20});
x=input('请输入你的出生月日:(月份和日期之间用。隔开)');
for i=1:12
if x>=s(i).first&&x<=s(i).last
fprintf('%s',s(i).zuo);
end
end
6. 绘制函数
,x∈[-10,10]的曲线。要求:
(1) 观察该函数在已知区间上有几个零点?有几个极值点?
clc;
clear;
ezplot('cos(x)*exp(2*sin(x))-sin(x)*exp(2*cos(x))',[-10,10]);
grid on
观察图像可知,该函数在[-10,10]区间内的零点个数为12个,极值点个数为12个。
(2)编程求出函数在已知区间上的极值,精度不低于0.01;
由图像可知,该函数是一个周期函数,所以我们不妨在[-10,-2]区间内求极值。
clc;
clear;
x1=-7:0.001:-6.5;
x2=-6:0.001:-5.5;
x3=-5.5:0.001:-5;
x4=-4.5:0.001:-4;
x=[x1;x2;x3;x4];
y=cos(x).*exp(2.*sin(x))-sin(x).*exp(2.*cos(x));
max(y(1,:))
min(y(2,:))
max(y(3,:))
min(y(4,:))
(3)容易验证:该函数的周期为2π,通过观察曲线的特点,能否设计一种方法,编程计算出该函数周期的一个近似值?(误差不超过0.01。)
clc;
clear;
x=0:0.001:2*pi;
y=cos(x).*exp(2.*sin(x))-sin(x).*exp(2.*cos(x));
for x1=1:0.001:2*pi
y1=cos(x+x1).*exp(2.*sin(x+x1))-sin(x+x1).*exp(2.*cos(x+x1));
if y1-y<0.005
disp(x1);
end
end
7. 已知一个长方体的长、宽、高分别为100cm,80cm,60cm,现在要将它切割成一个体积为200cm3 的小长方体(假设每次切割切下的仍是一个长方体)。在下面两种情况下完成实验任务:(a)每次切割的厚度在5cm到8cm之间;(b)每次切割的厚度为6cm.
(1)对于给出的厚度条件(a)和(b),能切出要求的长方体吗?
(2)自己设计一种切法(包括对三种面的切割顺序),算出这种切法每次切割面的面积、切割次数以及最后小长方体的边长;
(3)在你所设计的几种切法中,哪种方法的切割面面积总和最小?
略(大家有没有较系统的做法呢?坐等……)
8.已知长方形的长和宽分别为a和b,分别将长和宽进行n等分和m等分,此时,该长方形被分成了mxn个小的长方形.
(1)连接长方形的一条对角线,计算该对角线经过小长方形的个数;
(2)任取三个不共线的网格交点,作一条抛物线,计算该抛物线经过小长方形的个数;
(3)对上述两种情况,你能得出一般的结论吗?你能否将此问题推广到三维空间?
(1)
clc;
clear;
rectangle('Position',[0,0,8,4])
hold on
plot([0,8],[0,4])
x=input('要将长分为的份数为:');
y=input('要将宽分为的份数为:');
for m=0:8/x:8
plot([m,m],[0,4])
end
for n=0:4/y:4
plot([0,8],[n,n])
end
axis([-2,10,-2,6])
axis equal
上边这个程序可以用来探究长和宽的n等分点和m等分点下,对角线所经过的小长方形的个数。经过探究我们发现,经过的小长方形个数为m+n-(m,n),(m,n)表示m和n的最大公约数。
(2)
clc;
clear;
x1=input('请输入第一个点的横坐标:');
y1=input('请输入第一个点的纵坐标:');
x2=input('请输入第二个点的横坐标:');
y2=input('请输入第二个点的纵坐标:');
x3=input('请输入第三个点的横坐标:');
y3=input('请输入第三个点的纵坐标:');
x0=input('要将长分为的份数为:');
y0=input('要将宽分为的份数为:');
A = [x1^2, x1, 1;
x2^2, x2, 1;
x3^2, x3, 1];
Y = [y1;
y2;
y3];
C=A\Y;
a=C(1);
b=C(2);
c=C(3);
x=0:0.01:8;
y=a*x.^2+b*x+c;
plot(x,y)
hold on
rectangle('Position',[0,0,8,4])
for m=0:8/x0:8
plot([m,m],[0,4])
end
for n=0:4/y0:4
plot([0,8],[n,n])
end
axis([-2,10,-2,6])
axis equal
上边这个程序可以帮助我们来探究抛物线所经过的小长方形的个数。
经过多次试验,我们发现任取三个网格交点画出一个抛物线,这个抛物线所经过的小长方形的个数为m+n-3;
(3)一般情况在前两问已经说过了。至于推广到三维空间内,有点小复杂。(大家有没有较好的想法呢?评论区或私信我哦!)
9.科赫(Koch)曲线科赫曲线是由瑞典数学家科赫于1904年提出的,其生成方法是:先给定一条直线段F,将其三等分,保留两端的线段,将中间的一段用以该线段为边的等边三角形的另外两条边代替,得到图形F1然后,再对F1中的每一段按照上述方法修改,直到无穷,最后得到一条具有自相似结构的折线,这就是所谓的科赫曲线,如图3.7所示.
(1)试绘制科赫曲线;
注:此代码并非我自己写的,来自csdn博主hiter2014,这是链接MATLAB高效实现科赫曲线(Koch Curve)_matlab绘制科赫曲线-CSDN博客
n=input('请输入你想将此线段三等分的次数:');
points = [0 0; 1 0];
nums = 2;
for i = 1 : n
a = points(1 : nums - 1, :);
e = points(2 : nums, :);
b = a * 2 / 3 + e / 3;
d = a / 3 + e * (2 / 3);
c = (a + e) / 2 + (e - a) * [0 1; -1 0] / 3 * (sqrt(3) / 2);
points = [kron(a, [1 0 0 0]') + ...
kron(b, [0 1 0 0]') + ...
kron(c, [0 0 1 0]') + ...
kron(d, [0 0 0 1]') ; ...
points(nums, :)];
nums = (nums - 1) * 4 + 1;
end
plot(points(:, 1), points(:, 2));
axis([0 1 0 1]);
(2)将三条科赫曲线围在一起,就得到科赫雪花图形,如图3.8所示。试绘制科赫雪花图形.
此题在上一问的基础上加上两个旋转即可,我们只需知道一点绕另一点旋转后的坐标即可;
n=input('请输入你想将此线段三等分的次数:');
points = [0 0; 1 0];
nums = 2;
for i = 1 : n
a = points(1 : nums - 1, :);
e = points(2 : nums, :);
b = a * 2 / 3 + e / 3;
d = a / 3 + e * (2 / 3);
c = (a + e) / 2 + (e - a) * [0 1; -1 0] / 3 * (sqrt(3) / 2);
points = [kron(a, [1 0 0 0]') + ...
kron(b, [0 1 0 0]') + ...
kron(c, [0 0 1 0]') + ...
kron(d, [0 0 0 1]') ; ...
points(nums, :)];
nums = (nums - 1) * 4 + 1;
end
x=points(:, 1);
y=points(:, 2);
plot(x, y);
x2=0.5;y2=-sqrt(3)/6;t=2*pi/3;
x1= (x - x2)*cos(t) - (y - y2)*sin(t) + x2 ;
y1= (x - x2)*sin(t) + (y - y2)*cos(t) + y2 ;
hold on
plot(x1,y1)
t1=4*pi/3;
x3= (x - x2)*cos(t1) - (y - y2)*sin(t1) + x2 ;
y3= (x - x2)*sin(t1) + (y - y2)*cos(t1) + y2 ;
hold on
plot(x3,y3)
axis equal
练习二
1. 心形线在几何上可以这样生成:一个动圆沿一个定圆圆周外部无滑动地滚动(两个圆的半径相等),动圆圆周上的一固定点运动的轨迹就是心形线,因其形状像心脏而得名。其方程为ρ=a(1-cos(θ)),编写程序实现心形线的生成过程。
clc;
clear;
t=linspace(0,2*pi,100);
a=linspace(0,2*pi,100);
for i=1:100
ezplot('x^2+y^2-1')
x=2*cos(a(i))+cos(t);
y=2*sin(a(i))+sin(t);
x1(i)=2*cos(a(i))-cos(2*a(i));
y1(i)=2*sin(a(i))-sin(2*a(i));
hold on
plot(x,y,x1(i),y1(i),'r*')
hold on
plot(x1,y1)
axis off
axis equal
hold off
m(i)=getframe;
end
title('心形线的形成过程');
2.星形线的方程为x= a cos t,y= a sin t 编写程序实现星形线的生成过程 首先我们要知道星形线是如何生成的,让一个半径为a/4的圆在一个半径为a的圆内部,延圆的圆周旋转,小圆圆周上的任一点形成的轨迹即为星形线。
clc;
clear;
t=linspace(0,2*pi,100);
a=linspace(0,8*pi,100);
for i=1:100
ezplot('x^2+y^2-16')
x=3*cos(a(i)/4)+cos(t);
y=3*sin(a(i)/4)+sin(t);
x1(i)=4*cos(a(i)/4)^3;
y1(i)=4*sin(a(i)/4)^3;
hold on
plot(x,y,x1(i),y1(i),'r*')
hold on
plot(x1,y1)
axis off
axis equal
hold off
m(i)=getframe;
end
title('星形线的形成过程');
实际上,星形线的参数方程中,x=cos(t)^3 ,t表示的是圆上固定那个点转动的度数的四分之一。
本文由作者自己创作,由于时间原因,难免出现些许差错,还望大家多多批评指正。创作不易,希望大家多多鼓励。