给定一个公式字符串用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),且 ...
随机推荐
- shell操作钉钉机器人实现告警提醒
我们知道,之前的运维告警多通过mail 等方式通知到相应的人员,难以实现随时随地的查看.随着手机APP的发展,很多告警开始发送到IM软件上去.目前比较常用的是发送到微信和钉钉上,今天我们将重点放在钉钉 ...
- Atcoder/Topcoder 口胡记录
Atcoder/Topcoder 理论 AC Atcoder的❌游戏示范 兴致勃勃地打开一场 AGC 看 A 题,先 WA 一发,然后花了一年时间 Fix. 看 B 题,啥玩意?这能求? 睡觉觉. e ...
- HDU 4322Candy 最大费用最大流
由于被小孩子不喜欢的糖果的对小孩产生的效力是一样的,所以我们在网络流的时候先不考虑. 1 - 源点0到1~N个糖果,容量为1,费用为02 - 根据like数组,like[i][j] == 1时在糖果j ...
- Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)
Letters Removing 题意:给你一个长度为n的字符串,然后进行m次删除操作,每次删除区间[l,r]内的某个字符,删除后并且将字符串往前补位,求删除完之后的字符串. 题解:先开80个set ...
- 模板汇总——splay
#define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] ; , root; struct Node{ ], pre, sz; void init ...
- 2017福建省赛 L Tic-Tac-Toe 模拟
Kim likes to play Tic-Tac-Toe. Given a current state, and now Kim is going to take his next move. Pl ...
- HDU 5451 Best Solver 数论 快速幂 2015沈阳icpc
Best Solver Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Tota ...
- codeforces 801 D. Volatile Kite(数学题)
题目链接:http://codeforces.com/contest/801/problem/D 题意:求出一个最大值D,使得一个给定的凸多边形任意点移动范围在半径为D的圆中,都不会构成一个凹都边形. ...
- CF989B A Tide of Riverscape 思维 第七题
A Tide of Riverscape time limit per test 1 second memory limit per test 256 megabytes input standard ...
- 一起来聊一下 JavaScript 的用途和那些特性
JavaScript 简介 我们一起来聊一下 JavaScript,用它能做什么,它有哪些特性,以及一些跟它配合使用的技术. 什么是 JavaScript? JavaScript 最初的目的是为了&q ...