这篇文章对 Matlab 中的元编程进行了简单的介绍。Matlab 是一个古老而又高度专业化的语言。由于这一原因,缺乏很多在现代或者通用语言中拥有的特性。然而,用一些简单的工具,我们可以发现 Matlab 也可以足够灵活去进行非常简单的元编程。

什么是元编程?为什么用 Matlab 来做

粗浅的说,元编程是将程序视为数据的过程——意味着一个程序可以像一个普通的数据片段一样被制造并且被操作。像 Ruby 语言就显示出了一些作为元编程语言的特性。Matlab 未能提供这样的一套工具用于进行元编程。然而事实上用一点创造性就能实现,用一些简单的工具箱完成这一点。

注意如果把这一部分的内容称为元编程的话,可能会有一些夸张,但是我认为内容上已经足够接近去自证这样的标签。

前提条件

本文的代码能运行是基于如下条件的:

函数是可实例化的(first class objects)

函数可以被匿名定义

符号表达式可以变作程序执行.

粗略的讲, 这些使我们可以定义符号表达式,修改他们,而且使他们变为函数。这就是这篇文章的核心观点

使用和修改符号表达式

首先定义一个符号变量

x = sym('x');

MATLAB 将会将 x 当做符号来处理,而不是数字。 然后我们可以构造更复杂的表达式,例如:

>> x + x

ans =

2*x

>> x * x

ans =

x^2

>> sin(x)^2 + cos(x)^2

ans =

sin(x)^2 + cos(x)^2

当然,最后一个表达式恒等于1. MATLAB 也知道:

>> simplify(sin(x)^2 + cos(x)^2)

ans =

1

而且可以做微积分:

>> diff(3*x^2 + sin(x))

ans =

6*x + cos(x)

>> int(6*x + cos(x))

ans =

sin(x) + 3*x^2

>> taylor(exp(x), x, 0, 'Order', 10)

ans =

x^9/362880 + x^8/40320 + x^7/5040 + x^6/720 + x^5/120 + x^4/24 + x^3/6 + x^2/2 + x + 1

symbolic 工具箱有一个叫 matlabFunction 的函数,可以把表达式专为一个函数:

>> p = matlabFunction(x^2 + 2*x + sin(x))

p =

@(x)x.*2.0+sin(x)+x.^2

>> p(0.2)

ans =

0.6387

有此利器在手,我们就可以编写,能写程序的程序了。

傅里叶级数逼近

傅里叶级数是一种函数逼近,由不同周期的正弦、余弦进行线性组合构成。 一个实际函数 f(x) 可以由如下级数逼近:

f(x)≈a02+∑n=1∞ancos(nx)+∑n=1∞bnsin(nx)

where:

a0=1π∫π−πf(x)dxan=1π∫π−πf(x)cos(nx)dxbn=1π∫π−πf(x)sin(nx)dx

这个近似已经精确地由这几个函数描述了, 但是我们准备写一个程序来近似一个随机的真实的函数,就用这个级数的截断的版本。

元编程实现傅里叶级数近似

现在,我们要实现一个函数,接收一个函数作为参数,返回另一个函数,是输入函数的截断的傅里叶级数近似。 有些更好的方法来实现元编程, 这里只是作为元编程的优雅的示例。

这个函数应按照如下形式工作

>> g = fourierapprox(f, N);

其中 f 是一个函数, N 是 f逼近中的最高项,g 为得到的近似函数。

首先, 我们创建一个符号表达式(最终会被转为MATLAB函数), 定义为一个独立变量x 。然后添加series的第一项:

function [fn] = fourierapprox(f, N)

series = sym();

x = sym('x');

a_0 = (1/pi) * integral(f, -pi, pi);

series = series + (1/2)*a_0;

...

end

(注意,我们使用 MATLAB自带的数值方法来计算必要的积分。)

下一步, 我们需要向series中添加有限项 (N)的正弦跟余弦的线性组合 :

function [fn] = fourierapprox(f, N)

series = sym();

x = sym('x');

a_0 = (1/pi) * integral(f, -pi, pi);

series = series + (1/2)*a_0;

for n = 1:N

a_n = (1/pi) * integral(@(x) f(x) .* cos(n*x), -pi, pi);

series = series + a_n * cos(n*x);

b_n = (1/pi) * integral(@(x) f(x) .* sin(n*x), -pi, pi);

series = series + b_n * sin(n*x);

end

fn = matlabFunction(series);

end

最后一行很关键: 他将一个单纯的符号变量转为一个可执行的函数。 这意味着 fn 表现的跟硬编码的函数一样! 称之为 ‘元编程’ 是没问题的, 因为我们通过程序生成了这个函数。

执行这个函数

我们来用刚才的函数生成一些近似函数看看。

下面这个函数将使用特定的间距在同一坐标系内绘出原函数跟傅里叶近似函数

function [ output_args ] = plotfourierapprox(f, N, a, b)

fplot(f, [a b], 'r');

hold on;

pn = fourierapprox(f, N);

fplot(pn, [a b], 'b');

end

方波

>> plotfourierapprox(@square, 5, -5, 5)

>> plotfourierapprox(@square, 15, -5, 5)

f(x)=x3

>> plotfourierapprox(@(x) x.^3, 10, -4, 4)

最后的话

元编程不是MATLAB中典型的编程范式。 我想展示的是,这不但可能,而且实用。

matlab里的function编程,MATLAB 元编程介绍相关推荐

  1. python元编程_python元编程详解(3)

    今天转载一片非常精彩的文章供大家欣赏:参考文章链接. python开发者门户一个很好的学习python的网站,大家有时间可以多看看. 下面正式开始今天的内容: 在理解元类之前,你需要先掌握Python ...

  2. matlab里randn是什么,matlab中randn函数用法

    matlab中randn函数用法 MATLAB 中的randn函数 matlab函数 randn:产生正态分布的随机数或矩阵的函数 randn:产生均值为0,方差σ^2 = 1,标准差σ = 1的正态 ...

  3. matlab里simulink,如何运用MATLAB中的Simulink?

    摘要:文中首先分析了MATLAB/Simulink中DSP Builder模块库在FPGA设计中优点,然后结合FSK信号的产生原理,给出了如何利用DSP Builder模块库建立FSK信号发生器模型, ...

  4. matlab里tao怎么输入,matlab怎么运行程序

    本文收集整理关于matlab怎么运行程序的相关议题,使用内容导航快速到达. 内容导航: Q1:如何运行matlab程序 大哥你少了个赋值的运算,你的运行环境没错,就如楼上的,但是你想看的是结果.数据空 ...

  5. matlab里面的vpa函数,matlab用vpa函数之后怎么科学计数法

    MATLAB算π出错我输入vpa(pi,300) .结果是:ans =3.14159265358979311599796 vpa(pi,300)这样就可以了ans=3.1415926535897932 ...

  6. matlab里H是什么,matlab 中 hObject和handles区别

    h:指回调函数被调用对象的句柄:handles:是包含GUI中所有组件句柄的结构体,该结构体的域名由对象的TAG属性定义.也可以用来传递数据给其他的回调函数和主程序. 例如:创建一个包含button的 ...

  7. matlab里inline定义矩阵,Matlab中的inline函数_matlab中inline函数

    Matlab中的inline函数 1.有时为了描述某个数学函数的方便,可以用inline()函数来直接编写该函数,形式相当于M-函数,但无编写一个真正的MATLAB文件,就可以描述出某种数学关系.其调 ...

  8. python元编程_Python 元编程

    1.为函数添加包装器 总是存在这样的场景,在一个函数执行前后需要做一些操作处理,常见于日志创建.权限认证或者性能分析等.但有一个问题存在,那就是被装饰的函数,其元信息会丢失,函数引用会指向装饰器的返回 ...

  9. matlab里符号的写法,Matlab中特殊符号的写法

    Matlab的figure中输入上标.下标.特殊符号或字体 坐标轴标注: 1. 控制坐标轴尺度长度:set(gca,'XLim',[-pi/2 pi]) 2. 定制自己想标注的刻度: (1)set(g ...

最新文章

  1. @aspect注解类不生效_springboot:@Transactional注解 VS @Service注解
  2. linux6.6 ip 设置,centos 6.6默认iptable规则详解
  3. Python补充01 序列的方法
  4. CentOS6.8 mediawiki安装
  5. 基于python的文件加密传输系统 毕业论文_20183411 李丞灏 2020-2021 《python程序设计》 实验三 加密传输文件 实验报告...
  6. Constructor总结
  7. 7年老Android一次操蛋的面试经历,讲的太透彻了
  8. Java0steam_Java学习 - Stream 使用
  9. gif透明背景动画_做动画片用什么软件?99%的人用它就做出来了 - 动画制作博客...
  10. remote: 认证失败,请确认您输入了正确的账号密码。 fatal: Authentication failed
  11. 如何构建大数据分析平台
  12. javascript循环语句及函数
  13. 模仿人人网客户端应用源码
  14. 如何将OFD文件转成Word?教你2种实用方法
  15. 百度地图API 拾取坐标
  16. Android真正的静默安装
  17. 基于PC的工业控制系统的优缺点分析
  18. 计算机毕业设计ssm基于SSM的美妆分享网站vf952系统+程序+源码+lw+远程部署
  19. 理解深度学习中的卷积
  20. LeetCode-1789. 员工的直属部门

热门文章

  1. 主机故障一例——主机网卡灯不亮,主机启动不了
  2. 电阻系列知识(5)-电阻的阻值
  3. 工业modbus协议解析和转换
  4. Error Code 1318 Incorrect number of arguments for PROCEDUR
  5. 想知道自己的某个内存的小视频总时长?那这篇CSDN很适合你,快来看看Python如何实现求MP4时长吧(包含os模块和moviepy模块的全套基础操作)
  6. 男生学习Java软件开发更有优势吗及自学的难度如何?[图]
  7. 工程流体力学笔记暂记26 (流体在圆管中层流)
  8. 工具 - Mac端防休眠应用
  9. 太赫兹无线信道的测量、建模和分析
  10. SLAM十四讲——Pnp求解之DLT