数学函数教程:第 2 部分





4.00/5 (4投票s)
数学函数教程,第 2 部分
引言
在数学教程第一部分中,我向您展示了一个为我认识的一名数学学生创建的用于学习数学函数的程序。其中提供了四个预定义的数学函数。在第二部分中,您可以定义自己的数学函数,它们将由递归下降解析器(RDP)进行求值。
与第一部分的更改
在开始介绍 RDP 之前,先看一些与第一部分相比的更改:
- 创建了
MathUtilLib
,并将 MathFunction.cs、ExtensionMethods.cs 和 Options.cs 移入其中。 - 现在,Options 允许您设置文本框和数值UpDown控件的精度,以及数值UpDown控件的增量值。
- 添加了利用 Windows 事件日志的日志记录功能;您需要管理员权限才能使用它。如果您没有管理员权限或不想使用 Windows 事件日志,可以修改
MathUtilLib
中的 Logger.cs 文件,使其执行简单的操作,例如将日志信息写入文本文件。 - 创建了
RDPLib
,其中包含 RDP 和一个单元测试项目(稍后将详细介绍)。 - 更改了设置保存方式。一些评论者认为使用
%userprofile%\appdata
过于“以 Windows 为中心”。因此,为了简单和灵活,设置保存在一个文本文件中。现在您可以通过“文件 -> 保存”和“文件 -> 打开”来简单地保存和检索您的设置。有关详细信息,请参阅菜单栏“帮助 -> 说明”中的 HelpFile.html 文件。 - 修改了用户界面,增加了 编辑函数和 定义新函数的功能。
递归下降解析器 (RDP)
对于数学教程的第二部分,我采用了Herb Shildt 的递归下降解析器。 Shildt 先生关于 C 和 C++ 的书籍在几年前向我介绍了这个概念,我对其进行了修改,使其能够识别常量和数学函数,如余弦和正弦。
表达式解析器 会对诸如 1 + 2 * 3
这样的代数表达式进行求值。其优先级由称为文法的规则定义。因此,在表达式 1 + 2 * 3
中,2 会先乘以 3,然后再加上 1,结果是 7。如果我们使用括号,可以强制先进行加法运算,所以 (1 + 2) * 3
的求值为 9
。在这些表达式中,每个组成部分称为一个词法单元,是一个包含至少一个字符的 string
。在上述表达式中,数字 1
、2
和 3
是 TokenType NUMBER
,+、- 和括号是 TokenType DELIMITER
。RDP 的魔力在于 RecursiveDescentParser.cs 文件。起初,这段代码可能看起来有点令人望而生畏。但是,在 RDPUnitTestProject
中创建自己的测试方法(用 [TestMethod]
注释的方法)并使用调试器逐步执行它们是了解 RDP 工作原理的有效方法。
数学函数(sqrt、sin、cos 等)定义在 Functions.cs 中;常量(pi、e、G)定义在 Constants.cs 中。所有这些略显复杂的代码的最终结果是,您可以直接在函数参数文本框中输入表达式,例如:sqrt(3 * pi / 2)
,RDP 将得出正确答案,即 2.171
。RDP 不仅用于求值文本框控件中的表达式,还用于求值您定义的函数。与每个用户定义的函数相关联的是四个参数,称为 A
、B
、C
和 D
。您可以使用函数参数控件来设置这些参数的值。因此,当您定义自己的函数时,可以包含任何参数。例如,预定义的线性函数是 A * x + B
,其中 x
是 x 轴上的值。您可以为控件命名,因此对于线性函数,与 A
相关的控件被标记为“Slope
”(斜率),与 B
相关的控件被标记为“Y-intercept
”(y 轴截距)。移动滑块(“slider”)、单击数值UpDown控件或在文本框中键入值都会更改相应参数的值,从而相应地改变直线的斜率或 y 轴截距。
编辑函数
与数学教程第一部分一样,有四个预定义的数学函数。然而,在第二部分中,您可以编辑公式和标签,并设置参数的初始值。有关详细信息,请参阅菜单栏“帮助 -> 说明”中的 HelpFile.html 文件。
定义您自己的函数
您也可以定义自己的函数。有关详细信息,请参阅菜单栏“帮助 -> 说明”中的 HelpFile.html 文件。简而言之,从菜单栏选择“函数 -> 管理”来显示“数学函数详细信息”对话框,然后单击“添加新函数”。输入名称、公式、标签和初始值后,单击“保存”,然后单击“关闭”,新的 MathFunction
将被添加到数学函数列表中,新的 MathFunctionUserControl
将被添加到 FlowLayoutPanel
。
Using the Code
下载并使用 Visual Studio 打开 MathTutor.sln 解决方案。它包含五个项目:
ControlLib
- 一个包含.NET 用户控件的库MathTutor
- 解决方案的主窗体MathUtilLib
- 一个实用库,其中包含MathFunction
类等RDPLib
- 递归下降解析器 (RDP)RDPUnitTestProject
- 用于 RDP 的 Visual Studio 单元测试项目
按F6键构建解决方案。
主类仍然是 MathFunction
,但与前一版本不同的是,它包含一个 RDP 实例而不是 MyFunc
。
public class MathFunction
{
// public Func<double, double> MyFunc { get; set; } previous version
RecursiveDescentParser parser = new RecursiveDescentParser();
public String Name { get; set; }
public String Formula { get; set; }
...
}
结论
运用一点想象力,您就可以创建一些非凡的函数。这是我在测试项目时想到的一个:A * cos(x - B) + sqrt(abs(sin (C * x)))
。将参数 C
(“sin freq
”)设置为 1.0
,然后单击“启动计时器”按钮,观察会发生什么。
历史
- 版本 2.0.0.0