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解决精确计算的问题
最近有人在微信上给我发了一个数学题目,如下图: 我看了之后感觉很是简单,但是却想了半天才解出来.解出来后我想到了用程序再解一遍,然而精确计算的问题却让人头疼不已. 解题思路: 思路其实很简单,暴力求解 ...
随机推荐
- A trip through the Graphics Pipeline 2011_06_(Triangle) rasterization and setup
Welcome back. This time we’re actually gonna see triangles being rasterized – finally! But before we ...
- C#中ref和out的使用与区别
C#中ref关键字和out关键字所实现的功能差不多,都是指定一个形参按照引用传递而不是实参的副本传递.但是二者适用场景还是有些区别的:out适合用在需要retrun多个返回值的地方,而ref则适合用在 ...
- 孟加拉央行SWIFT攻击事件恶意木马分析(转)
第一章 分析概述 该恶意木马样本为运行于winodws平台上的PE文件(名称:evtdiag.exe).文件大小为64KB,编译时间是2016年2月5日. 经分析,该样本为定制的攻击SWIFT客户端程 ...
- Nginx配置(日志服务器中关于日志的产生)
一:概括 1.需要配置的概括 定义日志格式 日志的分割字段:^A 日志格式:IP地址^A服务器时间^A请求参数 配置location,记录请求日志到本地磁盘 将数据按照给定的日志格式存储到本地磁盘 二 ...
- ASP.NET MVC中从后台控制器(Controller)传递数据到前台页面视图(View)方式
方式一: 数据存储模型Model: public class CalendarEvent { public string id { get; set; } public DateTime start ...
- 让ecshop用户名、手机号、email登陆方法
让ecshop用户名.手机号.email登陆方法, 仅适用于没有做过任何平台整合的ECSHOP网站 修改文件: 1.includes/modules/integrates/ecshop.php ...
- Maven-009-Nexus 用户密码加密(安全必须)
信息数据大爆发的时代,我们关心什么?没错,数据安全!数据安全!数据安全!(重要事情说三遍,哈哈哈...) 之前我们存放在 maven settings.xml 文件中的 Nexus 私服用户密码都是明 ...
- elk实战分析nginx日志文档
elk实战分析nginx日志文档 架构: kibana <--- es-cluster <--- logstash <--- filebeat 环境准备:192.168.3.1 no ...
- java 删除目录、 文件
示例 import java.io.File; public class fileTest { public static void main(String []args){ String strVe ...
- RDIFramework.NET ━ 9.4 角色管理 ━ Web部分
RDIFramework.NET ━ .NET快速信息化系统开发框架 9.4 角色管理 -Web部分 角色管理模块主要为了方便框架权限的分配,提高权限分配的效率,减少重复设置权限的工作量.角色(用户组 ...