Java使用BigDecimal精确计算的简单公式计算器
由于工作需要,写了一个使用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精确计算的简单公式计算器的更多相关文章
- Java简单公式计算器
最近给公司开发业务代码时,碰到一个场景,简单描述是这样的: 客户要向咱们公司定制一件产品,这个产品呢,有很多属性,那公司得根据这些属性报价呀,怎么报价呢?公司针对某种类型的产品有一个基准价,在同类产品 ...
- BigDecimal精确计算工具类
前言 在实际开发中,遇到例如货币,统计等商业计算的时候,一般需要采用java.math.BigDecimal类来进行精确计算.而这类操作通常都是可预知的,也就是通用的.所以,写了个工具类来方便以后的工 ...
- java的数字精确计算问题-BigDecimal
java的数字运算,偶尔会出现精度的问题,以下阐述的 java的BigDecimal类的使用. 例如: System.out.println(0.9+0.3); 结果1.2 System.out.pr ...
- [转] 商业应用中Java浮点数的精确计算及表示
[From] https://blog.csdn.net/stevene/article/details/586089 问题提出 (1).浮点数精确计算 胜利油田三流合一项目中一直存在一个问题,就是每 ...
- BigDecimal精确计算及陷阱
BigDecimal通常在涉及到精确计算的时候会用到,下面是自己多次错误使用BigDecimal的总结. 结论: BigDecimal初始化小数时,尽量用字符串形式,例如new BigDecimal( ...
- 运用BigDecimal精确计算
package com.wzh.test; import java.math.BigDecimal; public class test { /** * @param args */ public s ...
- Java 根据年月日精确计算年龄
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Created b ...
- Java浮点数float,bigdecimal和double精确计算的精度误差问题总结
(转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...
- Java使用BigDecimal解决精确计算的问题
最近有人在微信上给我发了一个数学题目,如下图: 我看了之后感觉很是简单,但是却想了半天才解出来.解出来后我想到了用程序再解一遍,然而精确计算的问题却让人头疼不已. 解题思路: 思路其实很简单,暴力求解 ...
随机推荐
- Socket请求和Http请求的各自特点、区别及适用场景
Socket实现服务器与客户端之间的物理连接,并进行数据传输.主要有TCP/UDP两个协议.Socket处于网络协议的传输层.TCP:传输控制协议,面向连接的的协议,稳定可靠.当客户和服务器彼此交换数 ...
- JS-页面操作
--刷新页面 window.location.reload();
- asp
<%@LANGUAGE="%> <!--#include file="include.asp"--> <meta http-equiv=&q ...
- TOMCAT启动时报错:the CATALINA_HOME environment variable is not defined correctly
运行tomcat/bin目录下的startup.bat时报错:the CATALINA_HOME environment variable is not defined correctly 碰到这个问 ...
- zepto源码--核心方法3(属性相关)--学习笔记
继续$.fn方法 今天主要介绍几个跟属性操作相关的方法attr, removeAttr, prop, data attr 读取或设置dom的属性.如果没有给定value参数,则读取对象集合中第一个元素 ...
- Fixing “WARNING: UNPROTECTED PRIVATE KEY FILE!” on Linux
If you are getting this error then you probably reset the permissions on your hidden .ssh directory ...
- SQL2008关于quotename的用法
),) set @tbname='index' ---查这个表里的数据: print(@tbname) set @sql = 'select * from '+QUOTENAME(@tbname) p ...
- 下拉列表select显示ng-options
js中如何处理: it-equipment-list-maintenance-create-controller.js 'use strict'; myApp.controller( 'itEquip ...
- LeetCode Reconstruct Itinerary
原题链接在这里:https://leetcode.com/problems/reconstruct-itinerary/ 题目: Given a list of airline tickets rep ...
- 多个java文件编译并打成jar包经典方法
首先,多个java文件的编译 find . -type f -name *.java > compilelist (.代表当前路径) javac -cp "$CLASSPATH&quo ...