由于工作需要,写了一个使用BigDecimal运算的精确计算的计算器(然后发现其实比不用BigDecimal的并好不到哪里去)

只能做加减乘除

double类型的数字在千万级别的时候会转成科学计数法,我这个不会(我估计能有方法不以科学计数法显示)

其中用到的知识就是中缀表达式转后缀表达式,我是从这里学的:

http://www.cnblogs.com/mygmh/archive/2012/10/06/2713362.html

下面上代码吧:

这个方法需要一个参数,String类型公式,形如:"1+(2-3*4)/5";
这个方法用来对已经转换成后缀表达式的公式进行处理

public static BigDecimal getResult(String input){
//规范输入形式,避免用户输入中文括号
input=input.replaceAll("(","(");
input=input.replaceAll(")",")");
//对输入公式,按符号/数字,用空格分开,以便后面分组
String[] inputs=input.split("");
String format="";
for (int i=0;i<inputs.length;i++){
if (inputs[i].equals(" ")){
continue;
}else if (inputs[i].equals("(")||inputs[i].equals(")")||inputs[i].equals("+")||inputs[i].equals("-")||inputs[i].equals("*")||inputs[i].equals("/")){
format+=" "+inputs[i]+" ";
}else {
format+=inputs[i];
}
}
List<String> strings=changeInfixExpressionToPostfixExpression(format);
Stack<String> stack=new Stack<String>();
for (int i=0;i<strings.size();i++){
if (strings.get(i).equals("+")){
BigDecimal a=new BigDecimal(stack.pop());
BigDecimal b=new BigDecimal(stack.pop());
stack.add(b.add(a).toString());
}else if (strings.get(i).equals("-")){
BigDecimal a=new BigDecimal(stack.pop());
BigDecimal b=new BigDecimal(stack.pop());
stack.add(b.subtract(a).toString());
}else if (strings.get(i).equals("*")){
BigDecimal a=new BigDecimal(stack.pop());
BigDecimal b=new BigDecimal(stack.pop());
stack.add(b.multiply(a).toString());
}else if (strings.get(i).equals("/")){
BigDecimal a=new BigDecimal(stack.pop());
BigDecimal b=new BigDecimal(stack.pop());
//这里的1000是做除法以后计算的精确位数,就算1000位也并不会拖慢程序速度,一个公式0.01秒内就能算完,后面的是除不尽的四舍五入
stack.add(b.divide(a,1000,BigDecimal.ROUND_HALF_DOWN).toString());
}else {
stack.add(strings.get(i));
}
}
//返回的时候格式化一下,取四舍五入小数点后两位
return new BigDecimal(stack.pop()).setScale(2,BigDecimal.ROUND_HALF_DOWN);
}

这个方法呢,就是将输入的中缀表达式转成后缀表达式:

public static List changeInfixExpressionToPostfixExpression(String input){
List<String> resultList=new ArrayList<String>();
Stack<String> tempStack=new Stack<String>();
String[] splitArray=input.split(" ");
for (int i=0;i<splitArray.length;i++){
if (splitArray[i].equals("")){
continue;
}
//如果字符是右括号的话,说明前面一定有过左括号,将栈里第一个左括号之前全部添加到List里
if (splitArray[i].equals(")")){
while (!tempStack.peek().equals("(")){
resultList.add(tempStack.pop());
}
tempStack.pop();//去除前面的左括号
}else if (splitArray[i].equals("(")){
//如果是左括号,那么直接添加进去
tempStack.add("(");
}else if (splitArray[i].equals("+")||splitArray[i].equals("-")){
//如果是加减号,还需要再判断
if (tempStack.empty()||tempStack.peek().equals("(")){
tempStack.add(splitArray[i]);
}else if (tempStack.peek().equals("+")||tempStack.peek().equals("-")){
//读临时栈里的顶部数据,如果也是加减就取出来一个到结果列,这个放临时栈,如果是乘除就开始取到右括号为止
resultList.add(tempStack.pop());
tempStack.add(splitArray[i]);
}else {
while (!tempStack.empty()){
if (tempStack.peek().equals("(")){
break;
}else {
resultList.add(tempStack.pop());
}
}
tempStack.add(splitArray[i]);
}
}else if (splitArray[i].equals("*")||splitArray[i].equals("/")){
//如果是乘除
if (!tempStack.empty()){
//判断临时栈里栈顶是啥,如果是乘除,取一个出来到结果列,添这个进临时栈
if (tempStack.peek().equals("*")||tempStack.peek().equals("/")){
resultList.add(tempStack.pop());
}
}
tempStack.add(splitArray[i]);
}else {
//说明是非符号,都添加进去
resultList.add(splitArray[i]);
}
}
//遍历完了,把临时stack里的东西都加到结果stack里去
while (!tempStack.empty()){
resultList.add(tempStack.pop());
}
return resultList;
}
 

Java使用BigDecimal精确计算的简单公式计算器的更多相关文章

  1. Java简单公式计算器

    最近给公司开发业务代码时,碰到一个场景,简单描述是这样的: 客户要向咱们公司定制一件产品,这个产品呢,有很多属性,那公司得根据这些属性报价呀,怎么报价呢?公司针对某种类型的产品有一个基准价,在同类产品 ...

  2. BigDecimal精确计算工具类

    前言 在实际开发中,遇到例如货币,统计等商业计算的时候,一般需要采用java.math.BigDecimal类来进行精确计算.而这类操作通常都是可预知的,也就是通用的.所以,写了个工具类来方便以后的工 ...

  3. java的数字精确计算问题-BigDecimal

    java的数字运算,偶尔会出现精度的问题,以下阐述的 java的BigDecimal类的使用. 例如: System.out.println(0.9+0.3); 结果1.2 System.out.pr ...

  4. [转] 商业应用中Java浮点数的精确计算及表示

    [From] https://blog.csdn.net/stevene/article/details/586089 问题提出 (1).浮点数精确计算 胜利油田三流合一项目中一直存在一个问题,就是每 ...

  5. BigDecimal精确计算及陷阱

    BigDecimal通常在涉及到精确计算的时候会用到,下面是自己多次错误使用BigDecimal的总结. 结论: BigDecimal初始化小数时,尽量用字符串形式,例如new BigDecimal( ...

  6. 运用BigDecimal精确计算

    package com.wzh.test; import java.math.BigDecimal; public class test { /** * @param args */ public s ...

  7. Java 根据年月日精确计算年龄

    import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Created b ...

  8. Java浮点数float,bigdecimal和double精确计算的精度误差问题总结

    (转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...

  9. Java使用BigDecimal解决精确计算的问题

    最近有人在微信上给我发了一个数学题目,如下图: 我看了之后感觉很是简单,但是却想了半天才解出来.解出来后我想到了用程序再解一遍,然而精确计算的问题却让人头疼不已. 解题思路: 思路其实很简单,暴力求解 ...

随机推荐

  1. Excel 中 Index 和 Match 方法的使用

    MATCH函数(返回指定内容所在的位置) MATCH(lookup-value,lookup-array,match-type) lookup-value:表示要在区域或数组中查找的值,可以是直接输入 ...

  2. 序列化(Serialization)据为JSONP远端请求

    Insus.NET前些日子,有分享了一段代码,<使用JSONP跨域请求数据>http://www.cnblogs.com/insus/p/3512271.html 是使用jQuery的Da ...

  3. sdk 更新的时连接不上dl-ssl.google.com解决办法

    今天有朋友说sdk的更新不了,借了个VPN给他也没解决问题,后来还是他自己解决了,下面分享下经验 这里介绍一种不需要FQ的解决办法,修改C:\Windows\System32\drivers\etc下 ...

  4. node + nginx + mongo搭建负载均衡

    基于node和nignx和mongo搭建负载均衡 nginx配置: upstream back {                                                  # ...

  5. RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.7 版本发布

    历时数月,RDIFramework.NET V2.7 版本发布了,感谢大家的支持. RDIFramework.NET,基于.NET的快速信息化系统开发.整合框架,为企业或个人在.NET环境下快速开发系 ...

  6. cxf client在后台不通且chunk设置为false的时候不能在控制台输出请求日志

    场景: 服务编排框架支持编排webservice服务.call webservice的client是基于cxf做的.为了使用服务编排的开发者调试与定位问题方便,需要将webservice的请求与响应报 ...

  7. for循环和迭代

    迭代的一个时间复杂度最大就是n^2,而在for循环和迭代相结合的一个情况下则是一个排序组合,不再是一个简单n^2,而是阶乘n!.

  8. Js原生 双向数据绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 使用compass自动合并css雪碧图(css sprite)

    本文转载自: 使用compass自动合并css雪碧图(css sprite)

  10. 1.Cookie的定义和分类,及优缺点

    定义:用户请求网页,连接服务器,服务器在用户机上寻找属于它的cookie文件,如果有,就读取它的信息,如果没有就创建一个cookie文件发送给用户,存储在本地,用户可以通过浏览器选项设置是否接收服务器 ...