|
|||||||
![]() |
![]() |
||||||
|
|||||||
Forth 初学者指导 (使用Win32Forth)原著 J.V. Noble 编译 Forth 中文网, ForthChina.com 原文 Win32Forth 系统联机在线文档 有价值的程序示例为了解释如何构造一个有价值的程序,让我们开发一个二分法计算平方根的程序。我们将使用 FORmula TRANslator ftran201.f 以简化代码的外观(也就是说它隐藏了需要进行数据读取的存储的操作)。 首先,我们需要完整地理解算法:
开始编程,我们注意到,将要对三个点保持跟踪 : xa, xb 和 xp ,我们也需要对这三个点上的函数值保持跟踪 Ra, Rb 和 Rp. 我们也需要指定一个精度epsilon, 我们希望在其中确定根。 下面, 我们需要定义用户接口。一但我们有了一个开平方的子程序,应该如何访问它?因为我们需要通过名字来引用函数,同时也需要告诉它根的区间,我们希望有某种办法把名字作为参数传递给求根的过程。 我以前曾经开发了一个适合我自己的接口
比如
根将被留在浮点堆栈上。 把函数名字作为参数传递的代码在你装入 ftran201.f 时读入 — 在这个程序中使用的字是 use( , v: 和 defines。v: 在字典中创建一个哑项,在这个程序中命名为 dummy ,它可以在传递名字后执行实际的功能)bin_root。 这里是数据结构和标识符 MARKER -binroots \ say -binroots to unload \ Data structures
实际的求平方根的子程序 :) bin_root 将非常简单、很容易编写: : )bin_root ( xt --) ( f: Low High Precision -- root)
; 注意这个子程序由有意义的名字组成,所以它不需要注释。 )bin_root 自己通过堆栈注释来说明。第一行的注释就是 )bin_root 在数据堆栈上有一个“执行标记“,三个浮点数据在浮点堆栈上。这些是它的参数。( 参看 11d 关于 EXECUTE 的讨论 ) 。 执行标记用来改变哑字典项dummy的行为 :
在字 initialize 中使 dummy 功能变成我们计算根的行为。 最后的注释是 ( f: -- root) 说明 )bin_root 把答案留在浮点堆栈上。 从自顶向下的编程方面来说,因为我们是从程序的最后一个定义开始的,并按我们方式向前进。在 Forth 中,我们经常同时使用两种方法 — 自顶向下和自顶向上。 我们现在必须定义的关键字是 initialize , NotConverged? 和 NewPoint。我们可以开始初始化,因为概念上很简单: : initialize ( xt --) ( f: lower upper precision --)
; 字 ABORT" 如果在堆栈上遇到了数据堆栈上的 TRUE 标志则打印后面的信息,退出执行。 ABORT ( 没有 " ) 简单地退出执行。所以我们经常在一些像IF...THEN 一类的决策语句中见到它(参看 11d 的两个例子)。 ABORT" 被一个测试处理。为了使用一个测试作为 Fortran 类的表达式的一个函数(这个测试消耗浮点堆栈上的两个参数并在数据栈上留下一个标志), 我们必须定义一个同义词,原因是 ftran201.f 不能识别传统的关系操作符比如 > 或者 < . 定义是 : MoreThan ( f: a b) ( -- true if a>b)
f" MoreThan( Ra*Rb, 0)" 产生的代码是
它就是我们要的。我们已经解释了短语 defines dummy。短语 f" xa=" 等是把浮点栈上内容存入浮点变量操作的缩写。这样 f" xa=" 产生代码 XA F! . initialize 的其它部分是在 (a,b) 边界的端点处计算函数值。 NotConverged? 是一个对 ( 非 ) 转换的测试。 WHILE 在数据堆栈上有一个标志,就像 10a 中描述的那样,所以我们定义:
它产生代码
NewPoint 很清楚是这样的: : NewPoint
; 那就是,我们通过对分得到了新的估计值,计算了函数,并确定新的边界。其它的工作就是定义适当的顺序,通过将入 bin_rts.f 来测试结果。 FALSE [IF] Usage example:
[THEN] 最后,如果我们真的希望非常细心、计划程序重用,则加入适当的样板文件头,就像在文件中的那样。 |
||||||
|
|
||||||