不仅可以实现+,-,*,/,( ,) ,log ,ln,√ , ^ , cos ,sin,tan ,还支持最大500长度的字符运算。本程序是我上课的时候老师讲的,可能不是老师的原创,希望对有些同学有用,不扯了,上图:
import java.text.DecimalFormat;
import java.util.StringTokenizer;
/**
* 计算器的核心内容:
* 1.计算部分:必须建立在无错误的结论下
* 2.数据格式化
* 3.阶乘算法
* 4.错误提示
* @author asus
*
*/
public class Calc {
//设定最大的运算符长度
private static final int MAXLEN = 500 ;
/**
* 计算表达式的字符串形式
* 从左到右扫面,数字先入number栈,运算符入operator栈
* +-基本优先级为1 *÷的优先级为2,log ln sin cos tan n!的优先级为3,开方,乘方的优先级为4
* 括号内存运算法的优先级高于4
* 当前运算符优先级高于栈顶压栈,低于栈顶弹出一个运算符与两个数字进行运算
* 重复直到运算符大于栈顶
* 扫面完之后对剩下的运算符与数字依次进行计算
* @param str
*/
public static void process(String str , boolean drag_flag){
int weightPlus = 0 ; //记录同一个()的基本优先级
int topTop = 0 ; //数组计数器
int topNum = 0 ;
int flag =1 ; //判断正负 1为正数 -1为负数
int weightTemp = 0 ; //记录临时优先级的变化
int weight[] = new int[MAXLEN];
double[] number = new double[MAXLEN] ;
char ch , ch_gai , operator[] = new char[MAXLEN] ;
String num ; // 记录数字 str将以+-×÷()sctgl!√ ^分割,字符串之间即为数字
String experssion = str ;
StringTokenizer expToken = new StringTokenizer(experssion, "+-×÷()sctgl!√ ^");
int i =0 ;
while(i<experssion.length()){
ch = experssion.charAt(i);
//判断正负数
if(i==0){
if(ch == '-'){
flag = -1 ;
}
}else if(experssion.charAt(i-1)=='(' && ch == '-')
flag = -1 ;
//取得数字,将正负号交给该数字
if(ch>='0' && ch<='9' || ch=='.'|| ch=='E'){
num = expToken.nextToken();
ch_gai = ch ;
while(i<experssion.length() && (ch_gai>= '0' && ch_gai <= '9' || ch_gai == '.' || ch_gai == 'E')){
ch_gai = experssion.charAt(i++);
System.out.println("i的值为:"+i+" , ch_gai的值为:"+ch_gai);
}
if(i >= experssion.length())i-=1 ;
else i-=2 ;
if(num.compareTo(".") == 0) number[topNum++] = 0 ;
else {
number[topNum++] = Double.parseDouble(num)*flag ;
flag = 1 ;
}
}
//计算运算符的优先级
if(ch=='(') weightPlus += 4 ;
if(ch==')') weightPlus -= 4;
if(ch=='-' && flag == 1 || ch == '+' || ch == '-' || ch == '×' || ch == '÷' ||
ch == 's' || ch == 'c' || ch == 't' || ch == 'l' || ch == 'g' || ch == '!' || ch == '√' || ch == '^'){
switch(ch){
//+-的优先级最低
case '+':
case '-':
weightTemp = weightPlus + 1 ;
break;
//×÷的优先级为2
case '÷':
case '×':
weightTemp = weightPlus + 2 ;
break;
case 's':
case 'c':
case 't':
case 'l':
case 'g':
case '!':
weightTemp = weightPlus + 3 ;
break;
case '√':
case '^':
default:
weightTemp = weightPlus + 4 ;
break;
}
//如果当前优先级大于栈顶的元素,则直接入栈
if(topTop == 0 || weight[topTop -1] < weightTemp){
weight[topTop] = weightTemp;
operator[topTop] = ch ;
System.out.println("============"+ch+"========");
topTop++ ;
}else{ //否则将堆栈中的运算符逐个取出,直到当前栈顶部运算符的优先级小于当前运算符
while(topTop>0 && weight[topTop-1] > weightTemp){
switch(operator[topTop-1]){
case '+':
number[topNum-2] += number[topNum-1];
break;
case '-':
number[topNum-2]-=number[topNum-1];
break;
case '×':
number[topNum-2] *= number[topNum-1];
break;
case '÷':
if(number[topNum-1] == 0){
System.out.println("0不能为除数");
return ;
}
number[topNum-2] /= number[topNum-1];
break;
case '√':
//负值不能开偶次方
if(number[topNum-1] == 0 || (number[topNum-2] < 0 && number[topNum-1] % 2 == 0)){
System.out.println("平方数不存在或者负数不能开偶次行!");
return ;
}
number[topNum-2] = Math.pow(number[topNum-1], 1/number[topNum-2]);
break;
case '^':
number[topNum-2] = Math.pow(number[topNum-2], number[topNum-1]);
break;
case 's':
//角度
if(drag_flag){
number[topNum-1] = Math.sin(number[topNum-1]*Math.PI/180);
}else{
//此时为弧度
number[topNum-1] = Math.sin(number[topNum-1]);
}
topNum ++ ;
break;
case 'c':
if(drag_flag){
number[topNum-1] = Math.cos(number[topNum-1]*Math.PI/180);
}else{
number[topNum-1] = Math.cos(number[topNum-1]);
}
topNum++;
break;
case 't':
if(drag_flag){
if(Math.abs(number[topNum-1]%90) == 1){
System.out.println("tan取值有错误");
return;
}
number[topNum-1] = Math.tan(number[topNum-1]*Math.PI/180);
}else{
if(Math.abs(number[topNum-1] % Math.PI * 2) ==1){
System.out.println("tan取值有错误");
return;
}
number[topNum-1] = Math.tan(number[topNum-1]);
}
topNum++;
break;
//ln
case 'l':
if(number[topNum-1]<=0){
System.out.println("对数ln值有误");
return;
}
number[topNum-1] = Math.log(number[topNum-1]);
topNum++;
break;
//log
case 'g':
if(number[topNum-1]<=0){
System.out.println("对数log值有误");
return;
}
number[topNum-1] = Math.log10(number[topNum-1]);
topNum++;
break;
case '!':
if(number[topNum-1]<0){
System.out.println("阶乘数有误");
return ;
}
number[topNum-1] = getN(number[topNum-1]);
topNum++;
break;
}
//继续堆栈下一个元素判断
topNum -- ;
topTop -- ;
}
//将运算符压入栈中
weight[topTop] = weightTemp ;
operator[topTop] = ch ;
topTop++ ;
}
}
i++ ;
}
//依次取出堆运算中的运算符进行运算
while(topTop>0){
//直接将数组的后两位取出运算
switch(operator[topTop-1]){
case '+':
number[topNum-2] += number[topNum-1];
break;
case '-':
number[topNum-2] -= number[topNum-1];
break;
case '×':
number[topNum-2] *= number[topNum-1];
break;
case '÷':
if(number[topNum-1] == 0){
System.out.println("0不能为除数");
return ;
}
number[topNum-2] /= number[topNum-1];
break;
case '√':
//负值不能开偶次方
if(number[topNum-1] == 0 || (number[topNum-2] < 0 && number[topNum-1] % 2 == 0)){
System.out.println("平方数不存在或者负数不能开偶次方!");
return ;
}
number[topNum-2] = Math.pow(number[topNum-1], 1/number[topNum-2]);
break;
case '^':
number[topNum-2] = Math.pow(number[topNum-2], number[topNum-1]);
break;
case 's':
//角度
if(drag_flag){
number[topNum-1] = Math.sin(number[topNum-1]*Math.PI/180);
}else{
//此时为弧度
number[topNum-1] = Math.sin(number[topNum-1]);
}
topNum ++ ;
break;
case 'c':
if(drag_flag){
number[topNum-1] = Math.cos(number[topNum-1]*Math.PI/180);
}else{
number[topNum-1] = Math.cos(number[topNum-1]);
}
topNum++;
break;
case 't':
if(drag_flag){
if(Math.abs(number[topNum-1]%90) == 1){
System.out.println("tan取值有错误");
return;
}
number[topNum-1] = Math.tan(number[topNum-1]*Math.PI/180);
}else{
if(Math.abs(number[topNum-1] % Math.PI * 2) ==1){
System.out.println("tan取值有错误");
return;
}
number[topNum-1] = Math.tan(number[topNum-1]);
}
topNum++;
break;
//ln
case 'l':
if(number[topNum-1]<=0){
System.out.println("对数ln值有误");
return;
}
number[topNum-1] = Math.log(number[topNum-1]);
topNum++;
break;
//log
case 'g':
if(number[topNum-1]<0){
System.out.println("对数log值有误");
return;
}
number[topNum-1] = Math.log10(number[topNum-1]);
topNum++;
break;
case '!':
if(number[topNum-1]<0){
System.out.println("阶乘数有误");
return ;
}
number[topNum-1] = getN(number[topNum-1]);
topNum++;
break;
}
//取下一个元素计算
topNum -- ;
topTop -- ;
}
if(number[0]>7.3E306){
System.out.println("计算数组过大");
return ;
}
//数据显示:
System.out.println("最终计算答案为:"+dataShow(number[0]));
}
private static double getN(double n){
if(n==0)
return 1;
double sum = 1.0;
for(int s = 1 ; s <= n ; s++){
sum *= s ;
}
return sum ;
}
private static String dataShow(double n){
DecimalFormat format = new DecimalFormat("0.############");
return format.format(n).toString();
}
public static void main(String[] args) {
process("16+(7×l7)-90×g23+(1÷2)" ,true);
}
}
<span style="font-family: Arial, Helvetica, sans-serif;">由于比较懒,log就用g代替,ln就用l,sin用sin代替,cos用o代替,tan用t代替,不过这都不是重点,重点是这种处理的思想和方案.希望对大家有用,当然如果你喜欢,完全可以改一下做成一个android的应用,呵呵,我就做了一个,但是个人感觉本实验对android来说,并不是很优秀的算法,因为在每次输入的情况,都会对输入的字符串检测是否合法,显然对运算能力较弱的android来说有点吃力,不过,谁叫android也用java写呢????</span><span style="font-family: Arial, Helvetica, sans-serif;">呵呵</span>