65.9K
CodeProject 正在变化。 阅读更多。
Home

数学函数教程:第 2 部分

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4投票s)

2018年5月22日

CPOL

5分钟阅读

viewsIcon

11800

downloadIcon

502

数学函数教程,第 2 部分

引言

数学教程第一部分中,我向您展示了一个为我认识的一名数学学生创建的用于学习数学函数的程序。其中提供了四个预定义的数学函数。在第二部分中,您可以定义自己的数学函数,它们将由递归下降解析器(RDP)进行求值。

与第一部分的更改

在开始介绍 RDP 之前,先看一些与第一部分相比的更改:

  1. 创建了 MathUtilLib,并将 MathFunction.csExtensionMethods.csOptions.cs 移入其中。
  2. 现在,Options 允许您设置文本框和数值UpDown控件的精度,以及数值UpDown控件的增量值。
  3. 添加了利用 Windows 事件日志的日志记录功能;您需要管理员权限才能使用它。如果您没有管理员权限或不想使用 Windows 事件日志,可以修改 MathUtilLib 中的 Logger.cs 文件,使其执行简单的操作,例如将日志信息写入文本文件。
  4. 创建了 RDPLib,其中包含 RDP 和一个单元测试项目(稍后将详细介绍)。
  5. 更改了设置保存方式。一些评论者认为使用 %userprofile%\appdata 过于“以 Windows 为中心”。因此,为了简单和灵活,设置保存在一个文本文件中。现在您可以通过“文件 -> 保存”和“文件 -> 打开”来简单地保存和检索您的设置。有关详细信息,请参阅菜单栏“帮助 -> 说明”中的 HelpFile.html 文件。
  6. 修改了用户界面,增加了 编辑函数和 定义新函数的功能。

递归下降解析器 (RDP)

对于数学教程的第二部分,我采用了Herb Shildt 的递归下降解析器。 Shildt 先生关于 C 和 C++ 的书籍在几年前向我介绍了这个概念,我对其进行了修改,使其能够识别常量和数学函数,如余弦和正弦。

表达式解析器 会对诸如 1 + 2 * 3 这样的代数表达式进行求值。其优先级由称为文法的规则定义。因此,在表达式 1 + 2 * 3 中,2 会先乘以 3,然后再加上 1,结果是 7。如果我们使用括号,可以强制先进行加法运算,所以 (1 + 2) * 3 的求值为 9。在这些表达式中,每个组成部分称为一个词法单元,是一个包含至少一个字符的 string。在上述表达式中,数字 123TokenType 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 不仅用于求值文本框控件中的表达式,还用于求值您定义的函数。与每个用户定义的函数相关联的是四个参数,称为 ABCD。您可以使用函数参数控件来设置这些参数的值。因此,当您定义自己的函数时,可以包含任何参数。例如,预定义的线性函数是 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 解决方案。它包含五个项目:

  1. ControlLib - 一个包含.NET 用户控件的库
  2. MathTutor - 解决方案的主窗体
  3. MathUtilLib - 一个实用库,其中包含 MathFunction 类等
  4. RDPLib - 递归下降解析器 (RDP)
  5. 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,然后单击“启动计时器”按钮,观察会发生什么。

MathFunctionTutorWonderfullyWeirdFunction

历史

  • 版本 2.0.0.0
© . All rights reserved.