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

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

使用自然四则运算表达式即可,如: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等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对我们网站的支持。

(0)

相关推荐

  • java实现任意四则运算表达式求值算法

    本文实例讲述了java实现任意四则运算表达式求值算法.分享给大家供大家参考.具体分析如下: 该程序用于计算任意四则运算表达式.如 4 * ( 10 + 2 ) + 1 的结果应该为 49. 算法说明: 1. 首先定义运算符优先级.我们用一个 Map<String, Map<String, String>> 来保存优先级表.这样我们就可以通过下面的方式来计算两个运算符的优先级了: /** * 查表得到op1和op2的优先级 * @param op1 运算符1 * @param op2

  • java实现随机输出300题四则运算

    话不多说,请看代码: package demo; import java.util.Random; public class math { public static void main(String[] args) { String[] operate=new String[]{"+","-","×","÷"}; int[] numbers=new int[1000]; for(int i=1;i<=1000;i++)

  • java中实现四则运算代码

    代码的思路是通过正则判断计算每个最小的计算单元.以下是代码: import java.math.BigDecimal; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 计算器工具类 * @author shuqi * @date 2015-7-23 * @version since 1.0 */ public class CalculatorUtil { public static BigDecimal

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

    使用栈来实现,可以处理运算优先级. 使用自然四则运算表达式即可,如: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; im

  • Java编程实现对十六进制字符串异或运算代码示例

    前言:好久没有写博客,最近一年感觉真是好忙,各种做不完的工作.相信很多上班族都会有这种感觉.最近对NFC进行写卡操作,需要计算一个校验位.一般情况下,校验位多数是由前几个字节进行异或运算所得. 现在我就先说一下我使用的场景: 把一个16字节的数据写到CPU卡(如交通卡)里面,最后一字节是校验码---前十五字节异或. 我开始从网上找了一些别人写的算法发现计算后结果不对,或者就是写的太复杂了,于是自己就写了一个,感觉也比较简单,现在分享给大家,希望一起交流一下. 第一节:什么是异或运算(主要摘自百度

  • java&javascript自定义加密数据传输代码示例

    在开发应用过程中,客户端与服务端经常需要进行数据传输,涉及到重要隐私信息时,开发者自然会想到对其进行加密,即使传输过程中被"有心人"截取,也不会将信息泄露.对于加密算法,相信不少开发者也有所耳闻,比如MD5加密,Base64加密,DES加密,AES加密,RSA加密等等..可利用亦或,并,且,等进行简单加密. 示例代码中使用的^运算key=0x01,可自定义自己的规则.定义自己的运算,保证可逆数据不丢失即可.key也可定义,动态key. java代码 public static Stri

  • Java语言实现反转链表代码示例

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } 思路1: 要想反转链表,对于结点i,我们要把它的next指向它的前趋,因此我们需要保存前趋结点,同时,如果我们已经把i的next重新赋值,会无法找到i的后继,因此,在重新赋值之前,我们要保存i的后继. 代码:

  • Java创建与结束线程代码示例

    本文讲述了在Java中如何创建和结束线程的最基本方法,只针对于Java初学者.一些高级知识如线程同步.调度.线程池等内容将会在后续章节中逐步深入. 创建线程 创建普通线程有两种方式,继承Thread类或实现Runnable接口.示例如下. 方法1:继承Thread类 创建方法示例: public class MyThread1 extends Thread { @Override public void run() { //TODO Auto-generated method stub supe

  • switch实现一个两数的运算代码示例

    具体代码如下所示: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&quo

  • Java多线程阻塞与唤醒代码示例

    java线程的阻塞及唤醒 1. sleep() 方法: sleep(-毫秒),指定以毫秒为单位的时间,使线程在该时间内进入线程阻塞状态,期间得不到cpu的时间片,等到时间过去了,线程重新进入可执行状态.(暂停线程,不会释放锁) //测试sleep()方法 class Thread7 implements Runnable{ @Override public void run() { for(int i=0;i<50;i++){ System.out.println(Thread.currentT

  • 浅谈Java多线程的优点及代码示例

    尽管面临很多挑战,多线程有一些优点使得它一直被使用.这些优点是: 资源利用率更好 程序设计在某些情况下更简单 程序响应更快 资源利用率更好 想象一下,一个应用程序需要从本地文件系统中读取和处理文件的情景.比方说,从磁盘读取一个文件需要5秒,处理一个文件需要2秒.处理两个文件则需要: 5秒读取文件A 2秒处理文件A 5秒读取文件B 2秒处理文件B --------------------- 总共需要14秒 从磁盘中读取文件的时候,大部分的CPU时间用于等待磁盘去读取数据.在这段时间里,CPU非常的

  • Java编程之继承问题代码示例

    课堂练习: –在包bzu.aa中定义一个交通工具类(Vehicle): 1.属性--载客量(capacity) 2.方法 (1)无参构造方法(给capacity初始化值为2,并输出"执行交通工具类的无参构造方法.") (2)有参构造方法(传参给capacity初始化,并输出"执行交通工具的有参构造方法.") (3)capacity的set.get方法 (4)print方法:输出capacity –在包bzu.aa中定义一个汽车类(Car)继承交通工具类: 1.属性-

  • Java map的学习及代码示例

    前言 最近正在做的高校云平台项目中接触Map比较多,关于map的使用不是很熟悉,所以在此将map的几个方法再次学习下. Map与Collection 提到Map集合接口就不能不提到Collection集合接口,map和Collection都是集合接口,Collection中包含了我们经常用的list和set子接口:而Map是与Collection处于平级的地位:Collection中存储的是一组对象,而Map存储的是一个键值对(key/value). Map java为数据结构中的映射定义了一个

随机推荐