首先大家看到这个题目,可能会不屑一顾,呵呵,是的,起初我也认为这是个很简单的任务,当任务拿到手里后,经过我作为程序员来讲已经磨炼的无比通透的大脑来讲发现这其实是个坑。

故事的起因是这样的,想开发一款给学生和老师用的产品,那么其中就少不了留作业的模块,所以咯,老师留作业,学生肯定会答作业,那么老师留作业肯定有参考答案,学生答作业肯定有学生答案,如果老师是教语文、英语、历史、政治啥的烂七八糟学科的 那么没问题,直接拿参考答案和学生答案的字符串去比较就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个带数学公式的字符串的更多相关文章

  1. java List<String> 转换成带逗号的字符串

    使用commons-lang3-3.3.2.jar org.apache.commons.lang3.StringUtils.join(applyNameList, ",");

  2. 【百度地图API】多家地图API内存消耗对比测验(带源码)

    原文:[百度地图API]多家地图API内存消耗对比测验(带源码) 任务描述: 啊,美妙的春节结束了.酸奶小妹和妈妈的山西平遥之旅也宣告成功!距离平遥古城7km,有一个同样身为“世界文化遗产”的寺庙,叫 ...

  3. Word带数学公式发布博客

    Word公式编辑器无法直接上传博客,一个一个的转换LaTeX还要加$,十分麻烦. 下面是我昨天摸索出来的办法.作为博客新人,这个问题困扰我一晚上,能解决我也是非常高兴的. 如果各位前辈有好方法的话,请 ...

  4. java去中文

    java 去中文 package a.b; public class TrimCNTool { public static boolean checkCNChar(char oneChar) { if ...

  5. Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)

    Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...

  6. Java去除掉HTML里面所有标签的两种方法——开源jar包和自己写正则表达式

    Java去除掉HTML里面所有标签,主要就两种,要么用开源的jar处理,要么就自己写正则表达式.自己写的话,可能处理不全一些自定义的标签.企业应用基本都是能找开源就找开源,实在不行才自己写…… 1,开 ...

  7. DotNet,PHP,Java的数据库连接代码大全(带演示代码)

    C#数据库连接字符串 Web.config文件 <connectionStrings> <!--SQLServer数据库连接--> <add name="con ...

  8. php通过JavaBridge调用Java类库和不带包的自定义java类成功 但是调用带包的自定义Java类报错,该怎么解决

    php通过JavaBridge调用Java类库和不带包的自定义java类成功 但是调用带包的自定义Java类报错,Class.forName("com.mysql.jdbc.Driver&q ...

  9. Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结

    Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结 1. defer关键字1 2. try!形式存在的“不失败”机制3 3. Guard 4 4. swift的新语 ...

随机推荐

  1. 【js基础修炼之路】— null和undefined的区别

    在近期的复习期间遇到null和nudefined,于是通过查找资料,想写一篇文章来说明他们的区别.. javaScript高级程序设计: 在使用var声明变量但未对其加以初始化时,这个变量的值就是un ...

  2. java集合框架——List

    一.List接口概述 List有个很大的特点就是可以操作角标. 下面开始介绍List接口中相对于Collection接口比较特别的方法.在Collection接口中已经介绍的方法此处就不再赘述. 1. ...

  3. IOS NSOperationQueue(线程 封装操作)

    #import "HMViewController.h" @interface HMViewController () @end @implementation HMViewCon ...

  4. 在写EF 时把时间格式化的做法

    SELECT COUNT(l.LogSeq), date_format(l.CreateDate,'%Y-%m') CreateDateByMonth FROM LOL l WHERE l.Creat ...

  5. Family Gathering at Christmas(思维题)

    Family Gathering at Christmas 时间限制: 1 Sec  内存限制: 128 MB提交: 13  解决: 4[提交] [状态] [讨论版] [命题人:admin] 题目描述 ...

  6. EF问题集合

    1. 在使用数据迁移的过程中,如果手工删除了本地数据库之后,再次尝试连接被删除的数据库,会有以下提示: System.Data.SqlClient.SqlException (0x80131904): ...

  7. 命令搜索命令whereis与which

    whereis 命令名 #搜索命令所在路径及帮助文档所在位置,只能搜索系统命令. 选项: -b: 只查找可执行文件 -m: 只查找帮助文件 whoami whatis ls #ls 是什么命令 whi ...

  8. rbg的代码

    不得不赞rbg的代码,写的是真的好,各种异常都考虑到了,至少常见的异常没有了. 还有selective search的代码,也是很赞. 而edgebox的代码则不行啊,demo写的太死,而且代码里只能 ...

  9. 【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】

    一.创建线程的三种方式 · 继承Thread类 · 实现Runnable接口 · 实现Callable接口 二. 线程状态 · 线程名字 getName() · 线程活动情况 isAlive() · ...

  10. Angular项目下载启动

    Angular cmdb-front 新建项目流程 打开idea  New>Project 2,打开项目仓库,拷贝项目地址 拷贝项目路径,填写项目名 点击clone,然后一路Next 项目代码已 ...