面向对象设计与构造第三次作业
题目描述
本次作业中需要完成的任务为:读入一系列自定义函数的定义以及一个包含幂函数、三角函数、自定义函数调用、求导算子的表达式,输出恒等变形展开所有括号后的表达式。
在本次作业中,展开所有括号的定义是:对原输入表达式 \(E\) 做恒等变形,得到新表达式 \(E′\) 。其中, \(E′\) 中不再含有自定义函数,不再含有求导算子,且只包含必要的括号(必要括号的定义见公测说明-正确性判定)。
在本次作业中,自定义函数指自定义递推函数和自定义普通函数。
迭代内容概览
在第二次作业基础上,本次迭代作业增加了以下几点:
- 本次作业支持求导操作,新增求导算子 。
- 根据第五部分形式化表述,求导因子可以出现在很多位置,包括函数调用实参,三角函数内部等,注意考虑周全。
- 为了限制难度,在输入中,求导算子不会在自定义函数中出现,具体见第六部分-数据限制。
- 本次作业函数表达式中支持调用其他“已定义的”自定义普通函数(保证不会出现递归调用,具体见第六部分-数据限制)。
- 本周实验会着重指导求导将如何层次化实现。
基本概念(新增)
基本概念的声明
-
因子
-
自定义普通函数
- 自定义普通函数的定义形如
g(x, y) = 函数表达式,比如g(y) = y^2,g(x, y) = sin(x)*cos(y^2),h(x, y) = x + y。 g、h是函数的函数名。在本次作业中,保证函数名只使用g,h,且不出现同名函数的重复定义(因此每次最多只有 2 个自定义普通函数)。更具体的约束信息请看第六部分中的数据限制部分。x、y是递推函数的形参。在本次作业中,形参个数为 1~2 个。形参只使用x,y,且同一函数定义中不会出现重复使用的形参。- 函数表达式为一个关于形参的表达式。为了限制难度,我们规定求导因子不会出现在函数表达式中。函数表达式的一般形式参见形式化定义。
-
函数表达式中允许调用自定义普通函数,但保证不出现递归调用的情况,如:
g(x) = h(x) + 6 h(x) = g(x) * sin(x)不合法。
不允许先调用函数,再进行声明,也不允许调用未声明的函数,如:g(x) = h(x, x) + 666 h(x, y) = x*sin(y)不合法。
-
自定义普通函数的调用形如
g(因子, 因子),比如g(x^2),g(sin(x^2), cos(x)),h(1, 0)。 - 因子为函数调用时的实参,包含任意一种因子。
- 自定义普通函数的定义形如
-
-
求导因子
由
dx(表达式)这种算符构成,含义为对表达式中的x变量求导,其中可以出现多次求导的情况,详见求导因子的形式化描述。为了限制难度,我们规定求导算子不会出现在自定义函数的函数表达式和递推表达式中。
设定的形式化表述
自定义普通函数相关
- 自定义普通函数定义 → 自定义普通函数名 空白项 '(' 空白项 形参自变量 空白项 [',' 空白项 形参自变量 空白项] ')' 空白项 '=' 空白项 函数表达式
- 形参自变量 → 'x' | 'y'
- 自定义普通函数调用 → 自定义普通函数名 空白项 '(' 空白项 因子 空白项 [',' 空白项 因子 空白项] ')'
- 自定义普通函数名 → 'g' | 'h'
- 函数表达式 → 表达式(将自变量扩展为形参自变量,且一定不含求导因子) (注:本次作业中函数表达式不允许出现任何自定义递推函数调用,但允许出现自定义普通函数调用,保证不会出现递归调用的情况)
求导算子相关
- 求导因子 → 求导算子 空白项 '(' 空白项 表达式 空白项 ')'
- 求导算子 → 'dx'