Java实现四则混合运算代码示例

所属分类: 软件编程 / java 阅读数: 23
收藏 0 赞 0 分享

使用栈来实现,可以处理运算优先级。

使用自然四则运算表达式即可,如:4+(3*(3-1)+2)/2。无需把表达式先转换为逆波兰等形式。

package com.joshua.cal; 
import java.util.Collections; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
import java.util.Stack; 
public class Calculator { 
  private final Stack<Double> numStack = new Stack<Double>(); 
  private final Stack<Character> opStack = new Stack<Character>(); 
  private char currentOperator; 
  private char opStackTop; 
  private int i; 
  private String expression; 
  @SuppressWarnings("rawtypes") 
  public void exec(String expression) { 
    try { 
      clean(); 
      if (expression == null || expression.isEmpty()) { 
        throw new IllegalArgumentException("Blank Expression!"); 
      } 
      this.expression = expression; 
      opStack.push(TERMINATE_TOKENS.START_END_MARK); 
      List tokens = TOKENIZER.exec(expression 
          + TERMINATE_TOKENS.START_END_MARK); 
      for (; i < tokens.size(); i++) { 
        final Object token = tokens.get(i); 
        if (token instanceof Double) { 
          processOperand((double) token); 
        } else { 
          processOperator((char) token); 
        } 
      } 
    } catch (Throwable e) { 
      System.err.println(String.format( 
          "Incorret Expression: %s\nError: %s", expression, 
          e.getMessage())); 
    } 
  } 
  private void processOperand(final double operand) { 
    numStack.push(operand); 
  } 
  private void processOperator(final char currentOperator) { 
    this.currentOperator = currentOperator; 
    this.opStackTop = opStack.peek(); 
    char calMode = CALCULATE_MODE.getRule(currentOperator, opStackTop); 
    switch (calMode) { 
    case '>': 
      processStackHigerPriorityOperator(); 
      break; 
    case '<': 
      processStackLowerPriorityOperator(); 
      break; 
    case '=': 
      processStackEqualPriorityOperator(); 
      break; 
    default: 
      break; 
    } 
  } 
  private void processStackLowerPriorityOperator() { 
    opStack.push(currentOperator); 
  } 
  private void processStackHigerPriorityOperator() { 
    numStack.push(CALCULATE.exec(opStack.pop(), numStack.pop(), 
        numStack.pop())); 
    --i; // pointer back to the previous operator. 
  } 
  private void processStackEqualPriorityOperator() { 
    if (TERMINATE_TOKENS.START_END_MARK == currentOperator) { 
      System.out.println(expression + " = " + numStack.peek()); 
    } else if (')' == currentOperator) { 
      opStack.pop(); 
    } 
  } 
  public void clean() { 
    numStack.clear(); 
    opStack.clear(); 
    i = 0; 
  } 
  public static void main(String[] args) { 
    Calculator cal = new Calculator(); 
    cal.exec("4+(3*(3-1)+2)/2"); // = 8 
    cal.exec("4 + (-3 * ( 3 - 1 ) + 2)"); // = 0 
    cal.exec("4 +-/ (-3 * ( 3 - 1 ) + 2)"); // incorrect expression! 
    cal.exec("4.5+(3.2+3)/2"); // = 7.6 
    cal.exec("4.5+(3.2:3)/2"); // incorrect expression! 
    cal.exec("-4.5+(3.2-3)/2"); // = -4.4 
  } 
} 
enum CALCULATE { 
  INSTANCE; 
  public static double exec(final char operator, final double right, 
      final double left) { 
    switch (operator) { 
    case '+': 
      return left + right; 
    case '-': 
      return left - right; 
    case '*': 
      return left * right; 
    case '/': 
      return left / right; 
    default: 
      throw new IllegalArgumentException("Unsupported operator: " 
          + operator); 
    } 
  } 
} 
enum TERMINATE_TOKENS { 
  INSTANCE; 
  public static final char START_END_MARK = '#'; 
  private static final Map<Character, Integer> TOKENs = new HashMap<Character, Integer>(); 
  static { 
    // token, token id 
    TOKENs.put('+', 0); 
    TOKENs.put('-', 1); 
    TOKENs.put('*', 2); 
    TOKENs.put('/', 3); 
    TOKENs.put('(', 4); 
    TOKENs.put(')', 5); 
    TOKENs.put(START_END_MARK, 6); 
  } 
  private static Set<Character> NEGATIVE_NUM_SENSITIVE = new HashSet<Character>(); 
  public static synchronized Set<Character> getNegativeNumSensitiveToken() { 
    if (NEGATIVE_NUM_SENSITIVE.size() == 0) { 
      NEGATIVE_NUM_SENSITIVE.addAll(TOKENs.keySet()); 
      NEGATIVE_NUM_SENSITIVE.remove(')'); 
    } 
    return NEGATIVE_NUM_SENSITIVE; 
  } 
  public static boolean isTerminateToken(final char token) { 
    Set<Character> keys = TOKENs.keySet(); 
    return keys.contains(token); 
  } 
  public static int getTokenId(final char token) { 
    return TOKENs.get(token) == null ? -1 : TOKENs.get(token); 
  } 
  public static int getTokenSize() { 
    return TOKENs.size(); 
  } 
} 
enum CALCULATE_MODE { 
  INSTANCE; 
  private static char[][] RULES = { 
      // + - * / ( ) # 
      { '>', '>', '<', '<', '<', '>', '>' }, // + 
      { '>', '>', '<', '<', '<', '>', '>' }, // - 
      { '>', '>', '>', '>', '<', '>', '>' }, // * 
      { '>', '>', '>', '>', '<', '>', '>' }, // / 
      { '<', '<', '<', '<', '<', '=', 'o' }, // ( 
      { '>', '>', '>', '>', 'o', '>', '>' }, // ) 
      { '<', '<', '<', '<', '<', 'o', '=' }, // # 
  }; 
  static { 
    if (RULES.length != TERMINATE_TOKENS.getTokenSize() || RULES.length < 1 
        || RULES[0].length != TERMINATE_TOKENS.getTokenSize()) { 
      throw new IllegalArgumentException("Rules matrix is incorrect!"); 
    } 
  } 
  public static char getRule(final char currentOperator, final char opStackTop) { 
    try { 
      return RULES[TERMINATE_TOKENS.getTokenId(opStackTop)][TERMINATE_TOKENS 
          .getTokenId(currentOperator)]; 
    } catch (Throwable e) { 
      throw new RuntimeException("No rules were defined for some token!"); 
    } 
  } 
} 
enum TOKENIZER { 
  INSTANCE; 
  private static final StringBuilder BUFFER = new StringBuilder(); 
  private static String clearExpression(String expression) { 
    return expression.replaceAll(" ", ""); 
  } 
  private static Character PREVIOUS_CHAR; 
  private static void clean() { 
    BUFFER.delete(0, BUFFER.length()); 
    PREVIOUS_CHAR = null; 
  } 
  private static boolean processNegativeNumbers(final String exp, 
      final int index) { 
    char c = exp.charAt(index); 
    if (('+' == c || '-' == c) 
        && (PREVIOUS_CHAR == null || TERMINATE_TOKENS 
            .getNegativeNumSensitiveToken().contains(PREVIOUS_CHAR)) 
        && !TERMINATE_TOKENS.isTerminateToken(exp.charAt(index + 1))) { 
      BUFFER.append(c); 
      return true; 
    } 
    return false; 
  } 
  @SuppressWarnings({ "unchecked", "rawtypes" }) 
  public static List<?> exec(final String expression) { 
    clean(); 
    String exp = clearExpression(expression); 
    List result = new LinkedList(); 
    for (int i = 0; i < exp.length(); i++) { 
      char c = exp.charAt(i); 
      if (TERMINATE_TOKENS.isTerminateToken(c)) { 
        if (processNegativeNumbers(exp, i)) 
          continue; 
        if (BUFFER.length() > 0) { 
          result.add(Double.valueOf(BUFFER.toString())); 
          BUFFER.delete(0, BUFFER.length()); 
        } 
        result.add(c); 
      } else { 
        BUFFER.append(c); 
      } 
      PREVIOUS_CHAR = c; 
    } 
    return Collections.unmodifiableList(result); 
  } 
}

输出

4+(3*(3-1)+2)/2 = 8.0
4 + (-3 * ( 3 - 1 ) + 2) = 0.0
4.5+(3.2+3)/2 = 7.6
-4.5+(3.2-3)/2 = -4.4
Incorret Expression: 4 +-/ (-3 * ( 3 - 1 ) + 2)
Error: null
Incorret Expression: 4.5+(3.2:3)/2
Error: For input string: "3.2:3"

总结

以上就是本文关于Java实现四则混合运算代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以参阅:大话Java混合运算规则  浅谈Java变量赋值运算符及相关实例  Java大数字运算之BigInteger 等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对脚本之家网站的支持。

更多精彩内容其他人还在看

Java的面向对象编程基本概念学习笔记整理

这篇文章主要介绍了Java的面向对象编程基本概念学习笔记整理,包括类与方法以及多态等支持面向对象语言中的重要特点,需要的朋友可以参考下
收藏 0 赞 0 分享

Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法

这篇文章主要介绍了Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

基于Java实现杨辉三角 LeetCode Pascal's Triangle

这篇文章主要介绍了基于Java实现杨辉三角 LeetCode Pascal's Triangle的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java中Spring获取bean方法小结

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中获取Spring配置的bean呢?下面通过本文给大家介绍Java中Spring获取bean方法小结,对spring获取bean方法相关知识感兴趣的朋友一起学习吧
收藏 0 赞 0 分享

如何计算Java对象占用了多少空间?

在Java中没有sizeof运算符,所以没办法知道一个对象到底占用了多大的空间,但是在分配对象的时候会有一些基本的规则,我们根据这些规则大致能判断出来对象大小,需要的朋友可以参考下
收藏 0 赞 0 分享

剖析Java中的事件处理与异常处理机制

这篇文章主要介绍了Java中的事件处理与异常处理机制,讲解Java是如何对事件或者异常作出响应以及定义异常的一些方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Java的Struts2框架的结构及其数据转移方式

这篇文章主要介绍了详解Java的Struts2框架的结构及其数据转移方式,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

Java封装好的mail包发送电子邮件的类

本文给大家分享了2个java封装好的mail包发送电子邮件的类,并附上使用方法,小伙伴们可以根据自己的需求自由选择。
收藏 0 赞 0 分享

在Java的Struts中判断是否调用AJAX及用拦截器对其优化

这篇文章主要介绍了在Java的Struts中判断是否调用AJAX及用拦截器对其优化的方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

java多线程Future和Callable类示例分享

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。今天我们就来研究下Future和Callab
收藏 0 赞 0 分享
查看更多