给定一个公式字符串用java进行拆解并计算结果
需求很简单,给定一个字符串形式的公式规则,用java代码进行拆解,并能计算出结果。
♦考虑字符串中数字格式【整数、小数点】
♦考虑字符串中运算符【+-*/()】
♦考虑空格、运算规则【被0除】
以下是参考地址,里边有讨论部分的内容:
https://bbs.csdn.net/topics/380022283
下边是代码部分,可以作为一个工具类进行使用:
package test; import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Stack; /**
* 给定公式字符串拆解计算
* @author kerala
*
*/
public class CalUtil { static final String symbol = "+-*/()"; //运算符
static final String[] priority = {"+-", "*/", "()"}; //运算符优先级 /**
* 运算符比较器
*/
static Comparator<String> comp = new Comparator<String>() {
public int compare(String s1, String s2) {
int n1=0, n2=0;
for (int i=0; i<priority.length; i++) {
if (priority[i].indexOf(s1) >= 0) {n1 = i;}
if (priority[i].indexOf(s2) >= 0) {n2 = i;}
}
return (n1 - n2);
}
}; /**
* 输入字符串公式,返回结果
* @param exp
* @return
* @throws Exception
*/
public static String getResultByStrCal(String exp) throws Exception{
List<String> list = analyze(exp); //中缀转后缀
double result = cacl(list); //计算结果
return String.format("%.2f", result);//%.2f\n解释:%f ——浮点型 .2 ——两位小数点 \n ——换行
} /**
* 分析算式
* @param exp
* @return
* @throws Exception
*/
public static List<String> analyze(String exp) throws Exception {
if (exp == null) {
throw new Exception ("illegal parameter.");
}
exp = exp.replaceAll("\\s*", ""); //去掉所有的空格(为了方便中间存在空格算合法) List<String> list = new ArrayList<String>();
Stack<String> sym = new Stack<String>(); StringBuilder buf = new StringBuilder();
for (char c : exp.toCharArray()) {
if (symbol.indexOf(c) >= 0) { //如果是运算符
if (buf.length() > 0) { //如果有操作数
String v = buf.toString();
if (! v.matches("\\d+([.]\\d+)?")) {
throw new Exception ("illegal varaible("+v+").");
}
list.add(v);
buf.delete(0, buf.length());
} if (c == '(') {
sym.push(String.valueOf(c));
} else if (c == ')') {
String last = "";
while (sym.size() > 0) {
last = sym.pop();
if (last.equals("(")) {
break;
} else {
list.add(last);
}
}
if (!"(".equals(last)) {
throw new Exception ("illigal express.");
}
} else if (sym.size() > 0) {
String s = String.valueOf(c);
String last = sym.peek();
if (last.equals("(") || comp.compare(s, last) > 0) {
sym.push(s);
} else {
last = sym.pop();
list.add(last);
sym.push(s);
}
} else {
sym.push(String.valueOf(c));
}
} else { //不是运算符则当作操作数(因为已经去除所有空格,这里不再需要判断空格)
buf.append(c);
}
} if (buf.length() > 0) {
list.add(buf.toString());
} while (sym.size() > 0) {
String last = sym.pop();
if ("()".indexOf(last) >= 0) {
throw new Exception ("illigal express.");
}
list.add(last);
} return list;
} /**
* 计算
* @param list
* @return
* @throws Exception
*/
public static double cacl(List<String> list) throws Exception {
Stack<Double> val = new Stack<Double>();
double result = 0;
while (list.size() > 0) {
String s = list.remove(0);
if (symbol.indexOf(s) >= 0) {
double d1 = val.pop();
double d2 = val.pop();
if ("+".equals(s)) {
result = d2 + d1;
} else if ("-".equals(s)) {
result = d2 - d1;
} else if ("*".equals(s)) {
result = d2 * d1;
} else if ("/".equals(s)) {
result = d2 / d1;
} else {
throw new Exception ("illigal symbol("+s+").");
}
val.push(result);
} else {
if (!s.matches("\\d+([.]\\d+)?")) {
throw new Exception ("illigal variable("+s+").");
}
val.push(Double.valueOf(s));
}
} return result;
} }
测试一下:
package test; /**
* 测试拆分字符串公式运算
* @author kerala
*
*/
public class TestCal { /**
* @param args
* @throws Exception
*/
public static void main(String[] args) { String exp = "2.5*0.4+(2*5)";
try {
String result = CalUtil.getResultByStrCal(exp);
System.out.printf(result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("请输入正确计算公式");
} } }
目前测试了几个公式,都还正确,如果有问题,以后再补充!
给定一个公式字符串用java进行拆解并计算结果的更多相关文章
- 给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回
给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回 //统计字符串中出现的字符的出现次数 public function strNum(){ ...
- 给定一个字符串,根据字符出现频率排序--Java实现
题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列. 示例 1: 输入:"tree" 输出:"eert" 解释:'e'出现两次,'r'和't' ...
- 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 print-all-combinations-of-given-length
// 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 /* Input: set[] = {'a', 'b'}, k = 3 Output: aaa aab aba ...
- 数字使用相应的加密策略传递一个字符串后Java实现代码
公司采用公用电话传递数据,数据小于8整数位,为了确保安全, 在转移的过程中需要加密,加密规则如下面的: 第一个数据下降,附图然后各加5,和除以10的余数取代该数字, ...
- 给定一个字符串str,将str中连续两个字符为a的字符替换为b(一个或连续超过多个字符a则不替换)
需求:给定一个字符串str,将str中连续两个字符为a的字符替换为b(一个或连续超过多个字符a则不替换) 如: a 不替换 b 不替换 ab 不替换 ba 不替换 aba 不替换 aab 替换为 ...
- 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字符不改变,给定函数,编写函数 void Stringchang(const char*input,char*output)其中input是输入字符串,output是输出字符串
import java.util.Scanner; /*** * 1. 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字 ...
- JAVA 之 每日一记 之 算法( 给定一个正整数,返回它在 Excel 表中相对应的列名称。 )
题目: 给定一个正整数,返回它在 Excel 表中相对应的列名称. 例如: 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -> AA 28 -& ...
- 给定一个字符串,仅由a,b,c 3种小写字母组成。
package com.boco.study; /** * 题目详情 给定一个字符串,仅由a,b,c 3种小写字母组成. 当出现连续两个不同的字母时,你可以用另外一个字母替换它,如 有ab或ba连续出 ...
- 给定一个字符串里面只有"R" "G" "B" 三个字符,请排序,最终结果的顺序是R在前 G中 B在后。 要求:空间复杂度是O(1),且只能遍历一次字符串。
题目:给定一个字符串里面只有"R" "G" "B" 三个字符,请排序,最终结果的顺序是R在前 G中 B在后. 要求:空间复杂度是O(1),且 ...
随机推荐
- 从零开始搭建Java开发环境第二篇:如何在windows10里安装MySQL
1 下载安装包 1.1 压缩包 https://dev.mysql.com/downloads/mysql/ [外链图片转存失败(img-oesO8K09-1566652568838)(data:im ...
- 简明Python教程-函数联系笔记
1.实参与形参 在定义函数时给定的名称称作"形参",再调用函数时你所提供给函数的值称作“实参” 2.局部变量 所有变量的作用域是它们被定义的块,从定义它们的名字的定义点开始. 3. ...
- python入门(六)二次编码与文件操作
二次编码 密码本: ascii -- 没有中文 英文1字节 gbk -- 英文 8b(位) 1B(字节) 中文 16b 2B unicode -- 英文32b 4B 中文32b 4B utf-8 -- ...
- vue.js如何根据后台返回来的图片url进行图片下载
最近在做一个前端vue.js对接的功能模块时,需要实现一个下载图片的功能,后台返回来的是一串图片url,试了很多种方法,发现点击下载时出来的效果都是跳着到一个新的图片网页,后来经过一番琢磨,终于解决了 ...
- Windows平台python验证码识别
参考: http://oatest.dragonbravo.com/Authenticate/SignIn?returnUrl=%2f http://drops.wooyun.org/tips/631 ...
- HDU 6357 Hills And Valleys
Hills And Valleys 题意:给你一个序列, 可以翻转一次区间 [l, r] 求最大 非递减的 序列长度. 题解:枚举翻转区间,然后匹配. 如果不翻转区间, 那么就相当于用b[] = {0 ...
- [USACO07OCT]障碍路线 & yzoj P1130 拐弯 题解
题意 给出n* n 的图,A为起点,B为终点,* 为障碍,.可以行走,问最少需要拐90度的弯多少次,无法到达输出-1. 解析 思路:构造N * M * 4个点,即将原图的每个点分裂成4个点.其中点(i ...
- 反序列化JSON
本人编程生涯刚刚起步,以下是个人理解,如果有些不对的地方,请各位在评论区指出,如果有更详细的博客也可以推荐给我. 首先要根据JSON创建一个实体类,并且要实现Serializable接口,再创建一个J ...
- 【Offer】[39] 【数组中出现次数超过一半的数字】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数 ...
- Storm VS Flink ——性能对比
1.背景 Apache Flink 和 Apache Storm 是当前业界广泛使用的两个分布式实时计算框架.其中 Apache Storm(以下简称"Storm")在美团点评实时 ...