求导计算器
第⼀次:
⼀.表达式处理
题⽬要求表达式合法,⽽不合法的表达式显然是不能进⾏后续操作的,因此第⼀步要做的就是把不合法的表达式排除在外。
我的想法是这样的:
1. 把所有包含正确表达式不该有的字符的输⼊屏蔽掉
2. 把所有包含⾮法数字的表达式屏蔽掉
3. 把所有含有类似“+++”、“+-+”、“^++”等的表达式屏蔽掉,为下⼀步的拆分做铺垫
4. 当表达式差分成⼀个个项的时候,只要有⼀个项出现异常,整个串即为不合法
其中可能会出现⼀些细节问题,例如:
1. 判断⾮法字符的⽅法:我采⽤了最⼟的⽅法,把合法字符全部删除,如果还存在字符则显然⾮法。
2. 不合法数字的正则表达式:"(.*)[-\\+\\^][-\\+]( )+(\\d)(.*)"和"(.*)(\\d)( )+(\\d)(.*)"。
3. 处理分隔符时的⽅法:因为我采取的分割⼝是“+”,所以每两个项之间必须有⼀个加号,还要保证x^\\d中不能出现加号,因此要将
将x^\\d中可能出现的加号删除,将++换成+,--换成+,-+和-换成+-,这样就可以保证所有拆分出来的项都是合法的。当然如果表达式开头出现加号则在开头加上“0”,结尾出现加号则屏蔽掉。
⼆.项的处理
将切分好的项进⾏标准化,化成"(.*)*x^(.*)"的形式,以便使⽤*x^进⾏切割,将两边的数字进⾏处理,为防⽌数据溢出采⽤biginteger,⼀旦出现异常,则表达式显然不合法。将处理好的键值对存⼊hashmap中,通过幂次相等来合并同类项。
求导,更新hashmap中的数值等待输出。
三.输出处理
将每个键值对标准化成"\\d*x^\\d\\+"的形式,添加到同⼀个空字符串上,将系数或指数为0或1的项进⾏化简,最后删除最末尾的+即可输出。第⼆次:
⼀.表达式处理
和第⼀次基本相同,⼜略有差异。⾸先将不合法表达式粗略的排除在外。
具体操作如下:
1.排除空串(将所有‘\t’转化成‘ ’)
2.将所有包含⾮合法字符(串)的表达式排除(合法字符包括^*+- 以及数字、(x)、sin、cos)
3.将所有含有类似“++++”、“+-+-”、“^++”、“*++”等的表达式屏蔽掉,为拆分做铺垫
4.数字⾮法的正则表达式前多加⼊正负号,其他均与第⼀次相同
5.拆分好的项被称为乘法项,作为下⼀步处理的输⼊
⼆.乘法项的处理
将切分好的项再以*号分割,并将同类项合并,利⽤通式求导化简存⼊哈希表,x的幂次作为key,新建triangle类⽤与化简三⾓函数,最后输出。其他均与第⼀次相同。
三.化简处理
显然输出结果中会出现sinx^2+cosx^2等情况,我在作业中做了如下处理。
1. 合并同类项(以x为key)
正则匹配哈希值
2. 当出现asinx^(m+2)cosx^(n)+bsinx^(n)cosx^(n+2),ab>0时,可以进⾏化简提取通式将sin2+cos2化简成1,并降低幂次和系数
3. 当出现类似asinx^(m)cosx^(n)-asinx^(m)cosx^(n+2)时,可以将两项划为⼀项
4. 当出现1-sinx^2时合并成⼀项。最后按照第⼀次输出。
第三次:
⼀.表达式处理
1.判断是否有输⼊,如果有,则扫描⼀⾏字符,判断是否存在⾮法字符。
2.判断是否存在不合法数字,即:9  9;+++  9;^+  9;*+  9等(同时避免了++++;^++;*++等的出现。
3.判断是否存在不合法加减号,并替换成+,+-两种状态。
4.为满⾜以加号分割的需求,将所有⾮连接表达式的+号替换成&。
5.将切分好的各项存⼊term中
⼆.项的处理
1.将每个项⽤*号分割,并存⼊factor,同时判断拆分出来的表达式的类型,使⽤term递归。
2.在处理过程中,严格把控每⼀种情况,⼀旦出现⾮法表达式或项,⽴刻抛出异常。
三.Term类
1.将Term分为三类,
(1).x类:经过求导之后,直接输出导函数
(2).sin类:经过求导之后,输出原函数减⼀次幂乘上脱掉外层括号后的导函数
(3).cos类:经过求导之后,输出原函数减⼀次幂乘上脱掉外层括号后的导函数
2.脱括号:当整个表达式不包含在括号外的*和+时,可以脱掉⼀层括号,当不能再脱括号时转化成⼀个Factor类
3.求完导数后的结果套上⼀层括号,保存为⼀个字符串
4.将Term类数组中的所有导数相加即得到结果
四.Factor类
1.将Factor类⽤*号切割,把每⼀个切开的项⽤链式求导法则求导。
2.求完导数后的结果套上⼀层括号,保存为⼀个字符串
五.输出处理
本次输出我完全没有处理,还是求稳好⼀点吧。
关于互测:
三次作业我并没有采⽤对拍等⽅式进⾏互测bug,⽽是通过查看正则表达式的⽅法,寻求bug突破点,同时也发现了许多值得注意的地⽅:
1.多数同学采⽤的是Pattern和Matcher类来处理正则,⽽我直接⽤(.*)和matches⽅法来处理。
2.部分同学使⽤超长正则⼀次性匹配,在bug检查时简直⽆懈可击,但是可能会出现TLE等不可预知的情况
我的bug:
第⼀次出现在正则表达式中的+号和*号失误,导致空格的判断出现问题
第⼆次出现在化简时符号省略出错,导致输出变得诡异
第三次出现在参数带⼊错误,导致删括号的函数直接删掉了所有外围括号,将许多例如(1)+(1)等的测试点处理成了1)+(1,⽽后直接判错
可能我的代码并不是真正的⾯向对象,(不过相信会慢慢好起来的)。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。