由于工作需要,写了一个使用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. 利用脚本获取mysql的tps,qps等状态信息

    #!/bin/bash mysqladmin -uroot -p'123456' extended-status -i1|awk 'BEGIN{local_switch=0;print "Q ...

  2. Nodejs开发(1.Sublime Text 3配置)

    本例使用Sublime Text 3开发 原因: 1. 有开发提示: 2. 非常easy的调试运行: 下载Sublime Text 3,官网地址:http://www.sublimetext.com/ ...

  3. Nginx下Magento伪静态规则,适用于LNMP一键包

    文件名为:magento.conf(下载),将其放在 /usr/local/nginx/conf/ 文件夹下 然后在 /usr/local/nginx/conf/vhost/www.yourname. ...

  4. centos7 开机画面定制

    安装包 yum install plymouth-plugin-script 设置开机启动画面 mkdir /usr/share/plymouth/themes/tup 创建主题目录 cp /root ...

  5. Git add 常见用法

        Git add   git add [参数]  [--] <路径> //作用就是将我们需要提交的代码从工作区添加到暂存区,就是告诉git系统,我们要提交哪些文件,之后就可以使用gi ...

  6. fmt-重新格式化段落

    fmt供用户切分段落,使文本行数不要超出我们看到的屏幕范围. 如果电脑没有fmt(不是posix),需要安装coreutils包. 常用选项有两个: -s 切割较长的行,但不会将短行结合成较长的行. ...

  7. Java Servlet(六):HttpServlet实现原理(jdk7+tomcat7+eclipse)

    本篇记录了HttpServlet的实现过程,主要讲述了如何依赖Servlet,GenericServlet实现的原理. HttpServlet实现过程:1.是一个Servlet,继承自GenericS ...

  8. struts2-通配符映射(基本没啥卵用)和动态调用

    通配符 使用*代表任意字符 一般在action的name中使用*,并可以使用多个 可以使用{通配符的序号}引用对应的通配符所代表的值,序号从1开始 {0}代表整个URI 匹配规则 首先完全匹配,没有完 ...

  9. 获取Python安装目录

    >>> import sys>>> path=sys.executable>>> print (path)C:\Users\jumz-G\AppD ...

  10. ubuntu15.04安装Chrome浏览器

    首先到: https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb 下载最新的安装文件. 然后: sudo a ...