使用java去对比2个带数学公式的字符串
首先大家看到这个题目,可能会不屑一顾,呵呵,是的,起初我也认为这是个很简单的任务,当任务拿到手里后,经过我作为程序员来讲已经磨炼的无比通透的大脑来讲发现这其实是个坑。
故事的起因是这样的,想开发一款给学生和老师用的产品,那么其中就少不了留作业的模块,所以咯,老师留作业,学生肯定会答作业,那么老师留作业肯定有参考答案,学生答作业肯定有学生答案,如果老师是教语文、英语、历史、政治啥的烂七八糟学科的 那么没问题,直接拿参考答案和学生答案的字符串去比较就OK了。
但是,如果是作业是数学、物理、化学的话那么就少不了使用公式了,这里前端使用的是MyScript 手写公式,非常强大可以将手写的公式转成LATEX格式的字符串。
前端将字符串获取到了,传到后台,这时候就需要我去解析做匹配了,计算学生的做题答案和教师的参考答案是否匹配。
我这里简单描述一下我的心路历程:
第一天,和同事简单沟通后,他向我推荐了一个Maple的组件,这个组件呢,说实话,通过运行cmd命令行中找到om.exe然后运行它,直接上图:
可以发现,假设a+b 为学生答案,b+a为教师的参考答案,那么直接一相减如果得0就说明计算结果是相同的,说明学生答案和参考答案是匹配的。
如果使用Maple还是要注意一点,他只识别[]中括号,所以要用之前还需对字符串进行处理,将所有的大括号全部替换成中括号。
悲哀的发现,如果使用Maple的话需要用到两个jar包,Maple.jar、externalcall.jar,启动这个引擎还需要将他用到的dll文件全部放到公共的库中,什么是公共的库,就是你配置在环境变量中的路径。可以是java/bin目录。如果这些全部都配好了,你会发现各种错误等待着你去解决....
正是因为使用这种第三方的组件,导致自己的程序过于冗余还需解决各种出现的问题,所以最终我放弃了。
第二天,我就在想能不能自己去写一个比对公式的帮助类,既轻量级又和现有项目无缝兼容。有了目标就需要有具体的想法,我在想,如何设计这个类,才能解决目前的问题呢。咱们从头再捋一遍,我的需求是:将两个字符进行公式匹配,如果最终能匹配上返回一个true,匹配不上返回false。
ok,我是这样设想的,首先我会预定义一些公式,然后用这些公式去匹配这2个字符串,记录每个公式出现的次数,如果公式出现的次数相同,则说明这2个字符串则有可能是相同的,如果公式出现的次数不同肯定不是相同的,直接返回false,那么这种匹配方式可以算为第一层的匹配。如果第一层公式次数匹配成功,则需要再进行深度匹配,何为深度匹配,就是需要将所有的公式替换成空字符串。将所有的符号,{、}、[、]、(、) 、\各种特殊的符号替换成空字符串,省下的就只有一些字母和数字以及加减乘除等运算符号了,接下来只需要将a-z的字母替换成数字 就可以进行计算了,这里我会预先将a-z设置为1-26的数字,然后循环替换掉,最终剩下的就是一组运算公式了,例如2a+2b 替换后为 21+22 这种东东,最后只需要计算一下即可,这里会用到javaScript引擎,因为它本事是弱类型脚本语言是支持这样计算的,并且好处是加减乘除的运行顺序已经帮你处理了,好了,说了这么多了,思路有了,接下来就开始实践吧,直接上干货。
/**
* 将字符串转义成replace能替换的字符.
*
* @Title: convertStrByRep
* @author lmoran@163.com
* @param str
* @return
*/
public static String convertStrByRep(String str) {
str=str.replaceAll("\\\\", "\\\\\\\\")
.replaceAll("\\^", "\\\\\\^")
.replaceAll("[{]", "[{]")
.replaceAll("[}]", "[}]")
.replaceAll("\\[", "\\[")
.replaceAll("\\]", "\\]")
.replaceAll("[(]", "[(]")
.replaceAll("[(]", "[(]");
return str;
}
Util工具类中用到的方法
package cfs.test;
import cfs.core.util.MathUtil;
public class Test { public static void main(String[] args) throws Throwable {
String str1="a+b*b+d+\\sqrt {a^{2 }}(1){2}(3)\\pi";
String str2="a+b*c+d+\\sqrt { a^ {2 }}\\pi";
boolean bool=MathUtil.twoExprPattern(str1, str2);
System.out.println(bool); } }
测试类
最后再附上一张运算后的截图:
使用java去对比2个带数学公式的字符串的更多相关文章
- java List<String> 转换成带逗号的字符串
使用commons-lang3-3.3.2.jar org.apache.commons.lang3.StringUtils.join(applyNameList, ",");
- 【百度地图API】多家地图API内存消耗对比测验(带源码)
原文:[百度地图API]多家地图API内存消耗对比测验(带源码) 任务描述: 啊,美妙的春节结束了.酸奶小妹和妈妈的山西平遥之旅也宣告成功!距离平遥古城7km,有一个同样身为“世界文化遗产”的寺庙,叫 ...
- Word带数学公式发布博客
Word公式编辑器无法直接上传博客,一个一个的转换LaTeX还要加$,十分麻烦. 下面是我昨天摸索出来的办法.作为博客新人,这个问题困扰我一晚上,能解决我也是非常高兴的. 如果各位前辈有好方法的话,请 ...
- java去中文
java 去中文 package a.b; public class TrimCNTool { public static boolean checkCNChar(char oneChar) { if ...
- Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)
Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...
- Java去除掉HTML里面所有标签的两种方法——开源jar包和自己写正则表达式
Java去除掉HTML里面所有标签,主要就两种,要么用开源的jar处理,要么就自己写正则表达式.自己写的话,可能处理不全一些自定义的标签.企业应用基本都是能找开源就找开源,实在不行才自己写…… 1,开 ...
- DotNet,PHP,Java的数据库连接代码大全(带演示代码)
C#数据库连接字符串 Web.config文件 <connectionStrings> <!--SQLServer数据库连接--> <add name="con ...
- php通过JavaBridge调用Java类库和不带包的自定义java类成功 但是调用带包的自定义Java类报错,该怎么解决
php通过JavaBridge调用Java类库和不带包的自定义java类成功 但是调用带包的自定义Java类报错,Class.forName("com.mysql.jdbc.Driver&q ...
- Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结
Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结 1. defer关键字1 2. try!形式存在的“不失败”机制3 3. Guard 4 4. swift的新语 ...
随机推荐
- PointCNN 论文翻译解析
1. 前言 卷积神经网络在二维图像的应用已经较为成熟了,但 CNN 在三维空间上,尤其是点云这种无序集的应用现在研究得尤其少.山东大学近日公布的一项研究提出的 PointCNN 可以让 CNN 在点云 ...
- BestCoder Round #91 1001 Lotus and Characters
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6011 题意: Lotus有nn种字母,给出每种字母的价值以及每种字母的个数限制,她想构造一个任意长度的 ...
- AJAX(三):GET与POST
1.使用场景get是最常见的请求类型,最常用于向服务器查询某些信息仅次于get的是post请求,通常用于向服务器发送应该被保存的数据 2.使用get请求经常会发生一个错误,就是查询字符串的个是有问题, ...
- redis list类型
- theano中tensor的构造方法
import theano.tensor as T x = T.scalar('myvar') myvar = 256 print type(x),x,myvar 运行结果: <class 't ...
- Python-三元运算符和lambda表达式
一.三元运算符 #当满足条件1时,res=值1:否则res=值2 res = 值1 if 条件1 else 值2 举例说明: res=10 #简单的if else语句 if abs(res)>0 ...
- P1903 数颜色
题目 带修莫队题. 在询问上多加一个变量,记录是在那次修改之后的. 然后暴力修改. 就没了. 不过有一些修改的小技巧 #include<cstdio> #include<algori ...
- splay版
指针是个好东西 不过就是得判空 还有别忘传引用(其实应该都传引用) #include<cstdio> #include<algorithm> #include<iostr ...
- apache配置局域网访问
1.配置vhost.conf NameVirtualHost 192.168.2.74:80 <VirtualHost 192.168.2.74:80> DocumentRoot /var ...
- BZOJ1061: [Noi2008]志愿者招募(线性规划)
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5725 Solved: 3437[Submit][Status][Discuss] Descript ...