在上篇文章:LabVIEW编程实例:计算阶乘,学习for循环+移位寄存器+递归调用,通过一个求阶乘的例子已经演示了LabVIEW中基本递归VI程序的实现方法,但有很多小伙伴还是不太明白,下面再通过一个具体的例子给大家讲解一下其实现方法,加深LabVIEW中递归VI程序的理解。

例子说明

这儿以斐波那契数列(Fibonacci sequence)进行说明。斐波那契数列又称黄金分割数列,它是以兔子繁殖为例而引入的一个序列,所以又称为“兔子数列”,相信很多小伙伴在学C语言编程练习递归算法的时候应该接触过这个数列,这个数列在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用。

在数学上它以递归的方式进行定义,指这样的一个数列:0、1、1、2、3、5、8、13、21、34、55、89、144……,即前两个数为分别为0和1,从第3项开始,每项的值都等于其前两项之和。斐波那契数列Fib(n)用公式表示为:

Fib(n) = Fib(n-1) + Fib(n-2),其中,Fib(0) = 0,Fib(1) = 1

下面看下在LabVIEW中如何编写递归VI实现求解斐波那契数列Fib(n)中第n项的值。

LabVIEW中递归VI程序的特点

在讲具体的编程实现之前,大家应该先知道LabVIEW中递归VI的基本特点。

根据递归VI的定义,即程序在运行过程中能够调用自己的这样的VI就是递归VI程序,所以,对于递归VI程序,其特点包括以下几个方面:

(1) 首先它是一个子程序,所以程序功能完成后,要定义其图标/连接口,使其能作为子程序被调用;

(2) 在程序实现过程中,要能够动态调用自身,在LabVIEW编程环境中可通过VI引用动态调用及VI属性设置为可重入实现;

(3) 作为递归VI,要有使递归调用能够终止的条件,不能陷入无限调用的死循环中。

斐波那契数列递归的程序实现

针对上面递归VI的特点,下面看下如何实现斐波那契数列中第n项值的求解编程。

在前面板上放置一个输入控件n、一个输出控件Fib(n),用以求解斐波那契数列中第n项的值Fib(n),两个控件的数据类型皆设置为U32类型,输入输出参数定义完成后,其前面板及图标/连接口区域如下图所示:




labview 操作者架构_斐波那契数列


首先,先将这个VI程序设置为可重入的类型,在LabVIEW菜单中选择“文件”---->“VI属性”弹出VI属性设置对话框,在“类别”下拉框中选择“执行”,然后设置“重入”方式为“共享副本重入执行”,如下图所示:


labview 操作者架构_递归扫描文件设置深度_02


然后,编写程序代码,其程序框图如下图所示:


labview 操作者架构_大型的labview程序实例_03


在上面程序框图中,根据斐波那契数列的递归定义,先对输入的n值进行判断,当其为0和1时,Fib(n)的值分别输出0和1,当为其它值时,即选择结构的默认情况,其值为Fib(n-1)+Fib(n-2)。

在动态调用自身方面,使用“打开VI引用”和“通过引用调用”函数实现。

需要强调的是,在“打开VI引用”函数中,“选项”参数设置为8;“VI路径”参数设置为本VI所在的路径;“类型说明符”参数设置稍复杂些,先在这个参数上通过右键菜单创建一个常量,然后在这个常量的右键菜单中选择“选择VI服务器类”---->“浏览”,在弹出的文件选择对话框中选择当前VI即可,设置完成后,创建的常量外观自动变为如上面程序框图中所示的一输入一输出参数的样式。

成功打开VI引用后,通过两次调用“通过引用调用”函数中,分别计算Fib(n-1)和Fib(n-2)的值,然后将其相加即可得到Fib(n)的值。

Fib(0)=0和Fib(1)=1即为该程序递归的终止条件。

通过上面的程序就可求解斐波那契数列中任一项的值。

关于递归VI的总结

从上面的例子可以看出,对于递归VI总结如下:

(1) 递归VI就是在程序运行过程中能够调用自身;

(2) 在实现递归VI时,必须有一个明确的递归结束条件,不能使其陷入无限死循环中;

(3) 递归VI优点是在程序可读性上比较简洁明了,缺点是运行效率较低;

(4) 在递归调用过程中,会为每次调用的返回点、局部量开辟栈来存储,递归次数过多时容易造成栈溢出等缺点;

(5) 一般情况下,由于其运行效率的低效性,不建议过多使用递归VI程序。