Matlab训练4

你以为努力很难,其实甘于平庸更难。

Matlab官方帮助文档
1-17
采用函数min和max即可。(用linspace,subs等也是可以的,这里只列举这一种方法)

clc;clear;
x=1:0.0001:4;
y=2*x.^3-6*x.^2-18*x-7;
fprintf('该函数的最大值为%d,最小值为%d\n',max(y),min(y));

需要注意的是我这里的步长设置的很小,0.0001,有时你们要根据题目的具体精度要求情况来确定,因为有时精度太粗会导致数据误差较大。然后matlab还有一个求给定区间的函数的最小值fminbnd,这里以本题为例,看一下它的用法。

clc;clear;
syms x;
format long g;
%下面使用了匿名函数
y=@(x)2*x.^3-6*x.^2-18*x-7;
[xmin,ymin]=fminbnd(y,1,4);
fprintf('该函数的最小值为%d,当x=%d时取到\n',ymin,xmin);

这里使用了匿名函数来创建。匿名函数的优点有很多,具体的使用方法可以看这篇博客MATLAB带“@”的匿名函数表达方式与实例

1-18
这个题比较简单,注意一下第二个代码是错误的。

clc;clear;
x=input('请输入x的值:');
f=sin(x)/x^2-5*x^3;
if f<0
    disp('错误');
else
    disp(f);
end

下面这种写法带入了数学的思想,习惯性就这样写,但是运行时会报错说数组索引应该为逻辑值。这是因为在matlab里,a(i)代表a数组下标为i的元素的值。而在这里x,f均是变量,假若x的输入是1.2,那么在if判断里就是判断f(1.2)是否小于0,显然f不是一个数组,更找不到下标为1.2的元素的值。所以,千万不要混淆语法!!!

clc;clear;
x=input('请输入x的值:');
f(x)=sin(x)/x^2-5*x^3;
if f(x)<0
    disp('错误');
else
    disp(f);
end

1-19
这个题主要考察如何使用导数、极限、积分函数。
注意一下求 e x e^x 的函数为exp,以及第二个函数是定积分,而不是不定积分。

clc;clear;
syms x;
f1=sin(x)/x;
df1=diff(limit(f1,x,0),x,2)
f2=2*x^4+exp(-x);
df2=diff(int(f2,1,2),x,2)
f3=x^2+cos(x)*sin(x);
df3=diff(f3,x,2)

1-20
如果会做之前的提取每个数的各个位数,那这个题就很简单。由于数字较多,用数组存起来较好。sum为连加函数,prod为连乘函数。(不用函数的做法当然也是正确的),这种写法能够适应多位数的题目要求(比如输出1000以内或更大的数)

clc;clear;
num=[10:100];
a=[];   %存储满足条件的数
for i=10:100
   s=0;p=1;%s计算个位数相加的和,p计算个位数相乘的积
   s=sum(str2num(num2str(i)')');
   p=prod(str2num(num2str(i)')');
   if p>s
       a=[a,i];%满足条件就加入数组中
   end
end
disp('10~100之间各个位数相乘大于各个位数相加的数有:');
a

1-21
这个题有两种求法,一种是利用线性代数的知识来求解 (这种求法当仅当系数矩阵有逆矩阵才行,具体可以参考线性代数或高等代数的课本) ,另外一种就是用solve函数求解。
第一种做法:矩阵的逆矩阵或矩阵左除。
方程为:
{ 2 x 1 x 2 + 3 x 3 = 5 3 x 1 + x 2 5 x 3 = 5 4 x 1 x 2 + x 3 = 9 \begin{cases} 2x_1-x_2+3x_3=5 \\ 3x_1+x_2-5x_3=5 \\ 4x_1-x_2+x_3=9 \end{cases}
转化为 A x = B Ax=B 矩阵:
[ 2 1 3 3 1 5 4 1 1 ] x = [ 5 5 9 ] \begin{bmatrix} 2 & -1 &3 \\ 3 & 1 & -5\\ 4 & -1 & 1 \end{bmatrix} *x=\begin{bmatrix} 5 \\ 5 \\ 9 \end{bmatrix}
把矩阵看作一个整体,除到等式右边或者乘上逆矩阵,即 x = A x=A \ B B ,或者 x = A 1 B x=A^{-1}B ( A 1 A^{-1} A A 的逆矩阵)记住一定是A\B而不是B/A

clc;clear;
a=[2 -1 3;3 1 -5;4 -1 1];
b=[5 5 9]';
c=a\b	%左除
d=inv(a)*b	%乘以逆矩阵

第二种,solve函数,上一次做过这种题目

clc;clear;
syms x1 x2 x3
[x1,x2,x3]=solve([2*x1-x2+3*x3==5,3*x1+x2-5*x3==5,4*x1-x2+x3==9])

1-22
这是一个先对 l o g 2 ( 1 + c o s e x ) log_2(1+cose^x) 求导,再把 x = π x=\pi 带入求值的式子(也就是在指定点上求导)。把式子理清楚求解就很简单。
这里用的subs是把 x = π x=\pi 的值带入,而eval则是对最终结果进行数值上的化简,具体的用法可以自己查看帮助手册,这里只展示一下使用前和使用后结果的区别。

clc;clear;
syms x
f = log2(1+cos(exp(x)));
diff_f = diff(f);
y=eval(subs(diff_f,x,pi))

(图截的很丑将就一下吧)

在需要精确结果的时候,可以不进行化简,但是如果想知道具体的结果,可以进行化简,因为eval会保留精度。

1-23
抱歉这题少了一个要求。要求:变换后矩阵的大小由n行m列变为m行n列。 这样这题就变得容易起来。
先将a矩阵拉伸成为列向量或行向量,经过sort排序后reshape,抓住reshape函数的特性后再进行转置。
reshape函数shape的过程是: 对一个行(列)向量每隔n间隔取一个元素组成一个向量 b i b_i ,之后的向量 b i + 1 b_{i+1} 也是这样生成,只不过第一个元素往下移一位。这样做完后,得到n个大小为m的行向量,将这些行向量拼接得到矩阵。
reshape由于是按行来去,所以reshape后这个矩阵从左到右,从上到下读起来是按照顺序的,这不符合我们的要求,所以再进行了一次转置。例如:
[ 2 1 3 4 1 5 ] [ 5 1 1 2 3 4 ] [ 5 1 3 1 2 4 ] [ 5 1 1 2 3 4 ] \begin{bmatrix} 2 & -1 &3 \\ 4 & 1 & -5 \end{bmatrix}\rightarrow \begin{bmatrix} -5& -1 &1 &2 & 3 & 4 \end{bmatrix} \rightarrow \begin{bmatrix} -5 & 1 &3 \\ -1 & 2 & 4 \end{bmatrix} \rightarrow\begin{bmatrix} -5& -1 \\1 &2\\3 & 4 \end{bmatrix}
(这样要是还不理解我就要哭晕再厕所) 最后上代码!

clc;clear;
a=input('请输入一个矩阵:');
[n,m]=size(a);
a=sort(a(:));
b=reshape(b,n,m)'

1-24
思路很简单,就是第二问要注意是否会出现平局的情况(思路要严谨)
(1)

clc;clear;
a=[75 77 82 71 97 99 85 85 80 97 81 73];
ave=mean(a);
fprintf('A所有成绩的平均值为:%d\n',ave);

(2)我的做法是排序后直接取2——n-1的成绩,再平均。当然用max和min也可以

clc;clear;
a=[75 77 82 71 97 99 85 85 80 97 81 73];
b=[92 86 83 86 81 82 95 95 89 80 83 85];
a=sort(a);	b=sort(b);
credit_A=mean(a(2:11));
credit_B=mean(b(2:11));
if credit_A>credit_B
    disp('A胜');
elseif credit_A<credit_B
    disp('B胜');
else
    disp('平局');
end

1-25
这整个题都与斐波那契数列相关,斐波那契数列的编程实现有很多种 (比如递推、递归、矩阵、组合数、通式) ,感兴趣的可以自己下去深究,限于篇幅这里暂时只讲递推和递归版本。(关于递推和递归、斐波那契数列的会专门写两个博客,感兴趣的可以以后来看,没错我给自己挖了个坑)
1.递推版本
递推版本理解起来比较简单,就是根据斐波那契数列的递推式写的。

clc;clear;
f1=1;f2=1;
for i=3:20
    fn=f1+f2;
    f1=f2;
    f2=fn;
end
fprintf('斐波那契数列第20项为:%d\n',fn);

下方代码保存为sum_fibo.m(sum_fibonacci)文件,注意自定义函数名一定要有意义,不要随便定义abcd或者fff

function s=sum_fibo(n)
f(1)=1;f(2)=1;
for i=3:5
    f(i)=f(i-1)+f(i-2);
end
s=sum(f);
fprintf('斐波那契数列前%d项和为:%d\n',n,s);
end

2.递归版本(递归经典问题还有汉诺塔问题,学c的应该都会学到)
这个要难以理解一点,暂时可以理解为套娃和盗梦空间电影里的几重梦境

function fn=fib(n)
if n==1||n==2
    fn=1;
    return ;
else
    fn=fib(n-1)+fib(n-2);
end
%fprintf('斐波那契数列第%d项为:%d\n',n,fn);
end

想探索的可以把代码的注释去掉,然后运行。

clc;clear;
n=input('请输入一个数n:');
for i=1:n
    f(i)=fib(i);
end
fprintf('斐波那契数列前%d项的和为:%d\n',n,sum(f));

(2)找几个规律就会发现这是一个斐波那契数列,第n级台阶的走法就是斐波那契数列的第n项
如果要证明的话,可以反过来思考:假设第 n 2 n-2 级台阶的走法有 f ( n 2 ) f(n-2) 种,第 n 1 n-1 级台阶的走法有 f ( n 1 ) f(n-1) 种,第n级台阶的走法有 f ( n ) f(n) 种。那么登上第n级台阶有两种方法:一是从第 n 1 n-1 级台阶跨一级台阶到达,二是从第 n n 级台阶跨两级台阶到达。那么走到第 n n 级台阶的走法来自这两个渠道,即 f ( n ) = f ( n 1 ) + f ( n 2 ) f(n)=f(n-1)+f(n-2) ,也就是我们的结论。
这个题的代码和第一题求第20项的做法类似,就不写了。

发布了13 篇原创文章 · 获赞 1 · 访问量 446

猜你喜欢

转载自blog.csdn.net/amino_acid0617/article/details/104589487