分享一个计算器程序(经典的题目吧 :) 支持超级复杂表达式

pauliuyou 2008-07-09 12:28:26

package cross.pauliuyou.calculator.base;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.Vector;

/**
*
* @author 刘优
* @version 1.1
*
*
*
* */

public class CalculateUnit {
Vector<BigDecimal> numbers;
Vector<Character> operators;

public CalculateUnit(Vector<BigDecimal> nums,Vector<Character> ops) {
numbers = nums;
operators = ops;
int j = 0;
for (int i = 0; i < operators.size(); i++) {
if (getOpObjNum(operators.get(i)) == 1) {
numbers.add(i+j,numbers.get(i+j));
j++;
}
}
}
public BigDecimal calculate() throws CalculateException {
int [] levels = new int[operators.size()];
for (int i = 0; i < levels.length; i++) {
levels[i] = i;
}
sort(levels,operators);
for (int i = 0; i < levels.length; i++) {
int opPos = levels[i];
char op = operators.get(opPos);
int numPos = opPos;
int nullPos = -1;
int nullNum = 0;
boolean move = true;
for (int j = opPos; j >=0; j--) {
char tm = operators.get(j);
if (tm != '0') {
move = false;
}
else {
if (!move) {
nullPos = j;
}
nullNum++;
}
}
if (nullPos != -1 && move) {
numPos = nullPos;
}
else {
numPos -= nullNum;
}
int objnum = this.getOpObjNum(op);
switch (objnum) {
case 1:
case 2:
BigDecimal left = numbers.get(numPos);
BigDecimal right = numbers.get(numPos + 1);
BigDecimal rs = cal(left,right,op);
numbers.remove(numPos + 1);
numbers.remove(numPos);
numbers.add(numPos,rs);
operators.remove(opPos);
operators.add(opPos,'0');
break;
case 3:
default:
break;
}

}
return numbers.get(0);
}

protected static BigDecimal jie(BigDecimal x) throws CalculateException {
if (x.compareTo(BigDecimal.ZERO) == -1 || x.toString().indexOf(".") != -1) {
throw new CalculateException("负数或小数不允许算阶乘");
}
BigInteger result = BigInteger.ONE;
BigInteger num = new BigInteger(x.intValue() + "");
while (num.compareTo(BigInteger.ONE) == 1) {
result = result.multiply(num);
num = num.subtract(BigInteger.ONE);
}
return new BigDecimal(result);
}
private static BigDecimal sqrt(BigDecimal x) throws CalculateException {
if (x.compareTo(BigDecimal.ZERO) == -1) {
throw new CalculateException("负数不能开平方");

}
return new BigDecimal(Math.sqrt(x.doubleValue()) + "");
}
public static BigDecimal cal(BigDecimal x,BigDecimal y,char op) throws CalculateException {
//System.out.println("cal : " + x + op + y);
switch (op) {
case '+' :
return x.add(y);
case '-' :
return x.subtract(y);
case '*' :
return x.multiply(y);
case '/' :
if (y.compareTo(BigDecimal.ZERO) == 0) {
throw new CalculateException("不允许除零!");
}
return x.divide(y,MathContext.DECIMAL64);
case '!' :
return jie(x);
case 's' :
return sqrt(x);
case 'p' :
return x.pow(y.intValue());

default :
throw new CalculateException("不支持的运算符 :" + op);

}

}
private int getOpObjNum(char c) {
if (c == '!' || c == 's') {
return 1;
}
if (c == 'p') {
return 2;
}
if (c == '*' || c == '/') {
return 2;
}
if (c == '+' || c == '-') {
return 2;
}
return 0;
}
private int getLevel(char c) {
if (c == 'p') {
return 70;
}
else if (c == '!' || c == 's') {
return 60;
}
else if (c == '/') {
return 50;
}
else if (c == '*') {
return 49;
}
else if (c == '-') {
return 40;
}
else if (c == '+') {
return 39;
}

return 0;
}
private void sort(int [] in,Vector<Character> ops) {
for (int i = 0; i < ops.size(); i++) {
int t = getLevel(ops.get(in[i]));
int pos = i;
for (int j = i + 1; j < ops.size(); j++) {
int t2 = getLevel(ops.get(in[j]));
if (t2 > t) {
t = t2;
pos = j;
}
}
if (pos != i) {
int ttt = in[i];
in[i] = in[pos];
in[pos] = ttt;
}
}
}
public double oldCalculate(Vector<BigDecimal> numbers,Vector<Character> operators) throws CalculateException {
BigDecimal d = null;
while (operators.size() > 0) {
for (int i = 0; i < operators.size(); i++) {
char c = operators.get(i);
if (getLevel(c) == 0)
if (c == '*' || c == '/') {
d = cal(numbers.get(i),numbers.get(i + 1),c);
numbers.remove(i + 1);
numbers.remove(i);
numbers.add(i,d);
operators.remove(i);
break;
}
boolean hasMutli = false;
for (int j = i + 1; j < operators.size(); j++) {
if (operators.get(j) == '*' || operators.get(j) == '/') {
hasMutli = true;
break;
}
}
if (!hasMutli) {
d = cal(numbers.get(i),numbers.get(i + 1),operators.get(i));
numbers.remove(i + 1);
numbers.remove(i);
numbers.add(i,d);
operators.remove(i);
break;
}
}
}
return numbers.get(0).doubleValue();

}
public String toString() {
return "num : " + numbers.toString() + "\nops : " + operators.toString();
}

}

...全文
516 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
genius5865853 2009-07-30
  • 打赏
  • 举报
回复
说实话,现在很少有人自己动手写这么大量的代码了,我想问一下,您所给出的全部都是自己写的对吗?

如果带上注释的话一定是不错的代码。


期待中。。。。。。。。。。。。。。。
ccc_moriya 2008-12-25
  • 打赏
  • 举报
回复
留位学习。。。。
flyingzou 2008-11-11
  • 打赏
  • 举报
回复
能加点注释吗?方便我们新手学习~
pauliuyou 2008-07-18
  • 打赏
  • 举报
回复
希望大家能从中学到点什么 就是最大的收获了.
pauliuyou 2008-07-18
  • 打赏
  • 举报
回复
呵呵, 多谢鼓励. . 最近有点忙, 没时间改造. .
syueo 2008-07-17
  • 打赏
  • 举报
回复
好 lz真强!
kinghukyoun 2008-07-15
  • 打赏
  • 举报
回复
超级菜鸟
看见强帖强人
不禁mrak一下
向LZ学习!
jishu_vip 2008-07-15
  • 打赏
  • 举报
回复
不错!


这么有耐心。


顶一个!
Calvin_Lee 2008-07-15
  • 打赏
  • 举报
回复
代码好强! 但是我看起来很费劲!!因为没一句注释!!
起码在方法,类注释说明一下要实现什么功能吧!~!~!
zhangwin3 2008-07-15
  • 打赏
  • 举报
回复
顶。。。。。。
eks_222 2008-07-15
  • 打赏
  • 举报
回复
我刚刚在看java的书
感觉看这个程序还有难度.........

不过,还是埋头苦战......
aking21alinjuju 2008-07-15
  • 打赏
  • 举报
回复
谢谢分享啊
xujiaxiang 2008-07-15
  • 打赏
  • 举报
回复
非常的强大!佩服!
chenyanpan 2008-07-15
  • 打赏
  • 举报
回复
编程就需要有这种耐心,毅力
小郭小郭小郭 2008-07-15
  • 打赏
  • 举报
回复
好多代码,很强,lz真NB
numen_wlm 2008-07-15
  • 打赏
  • 举报
回复
mark
jdlsfl 2008-07-14
  • 打赏
  • 举报
回复
lz真勤奋!学习
pauliuyou 2008-07-14
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 gloomy98 的回复:]
一来就看见这个帖子,不错呢.

试了一下 999p9999, 机子挂掉了,不过不怪lz
[/Quote]

呵呵, 试了下. 我的机器能承受住这个计算.
计算9999! 才是真正的挑战
pauliuyou 2008-07-14
  • 打赏
  • 举报
回复
看来问题还是出在语法检查程序中...

我想的还是不够啊. 需要多测试发现问题. 呵呵.
pauliuyou 2008-07-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 billgacsli 的回复:]
LZ真强!!
想当初,被括号强奸死,没括号还好弄点

刚在看,因为楼主设计的比较好,还支持单目运算,所以括号的用法有点小问题
比如表达式“1+5*(-3)”或者“1+5*(3)”,将会报异常,而“1+2*(-3)+6-3”则能正确计算

就是语法检查sytax()中的左括号检查语句“if (i > str.length() - 5)”改为“if (i > str.length() - 2)”来匹配上述报异常的情况
楼主怎么看??
[/Quote]
呵呵, 好. 感谢指导, 我试试
加载更多回复(19)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧