千锋教育论坛

查看: 770|回复: 0

支持括号的仿Android计算器

[复制链接]

6

主题

211

帖子

480

积分

牛人

Rank: 3Rank: 3

发表于 16-4-28 16:43:42 | 显示全部楼层 |阅读模式
  支持括号的仿Android计算器
  1.   package com.fire.utils;

  2.   import java.text.DecimalFormat;

  3.   import java.text.NumberFormat;

  4.   import java.util.ArrayList;

  5.   import java.util.List;

  6.   import java.util.StringTokenizer;

  7.   /**

  8.   * 工具类

  9.   *

  10.   * @author FireAnt

  11.   *

  12.   */

  13.   public class Tools {

  14.   public static int i = 0;

  15.   /**

  16.   * 计算一个合法的表达式的值

  17.   * @param exp

  18.   * @return

  19.   */

  20.   public static String cal(String exp) {

  21.   // 特殊表达式的处理方式

  22.   if (exp.length() == 0) {

  23.   return "";

  24.   } else if (exp.length() == 1) {

  25.   if (exp.equals(".")) {

  26.   return "0";

  27.   } else {

  28.   return "";

  29.   }

  30.   } else if (exp.matches(".*÷0.*")) { // 0作为除数

  31.   return "∞";

  32.   } else if (exp.matches(".*[+-/×÷]")) {

  33.   exp = exp.substring(0, exp.length() - 1);

  34.   if (exp.equals(".")) {

  35.   return "0";

  36.   }

  37.   }

  38.   // 如果表达式中有括号则递归计算

  39.   if (exp.contains("(")) {

  40.   // 找出最后一个左括号

  41.   int left = exp.lastIndexOf("(");

  42.   // 找出第一个右括号

  43.   int right = exp.indexOf(")");

  44.   // 获取第一个子表达式

  45.   String subExp = exp.substring(left + 1, right);

  46.   // 计算子表达式的结果

  47.   String res = cal(subExp);

  48.   // 用计算出来的结果替换子表达式

  49.   exp = exp.substring(0, left) + res + exp.substring(right + 1);

  50.   // 递归计算新的表达式

  51.   exp = cal(exp);

  52.   }

  53.   // 格式化表达式

  54.   String newExp = formatExp(exp);

  55.   List opts = getOptions(newExp);

  56.   List nums = getNums(newExp);

  57.   // 先处理乘除

  58.   for (int i = 0; i < opts.size(); i++) {

  59.   char opt = opts.get(i);

  60.   if (opt == '÷' || opt == '×') {

  61.   opts.remove(i);

  62.   double d1 = nums.remove(i);

  63.   double d2 = nums.remove(i);

  64.   if (opt == '÷') {

  65.   d1 = d1 / d2;

  66.   } else {

  67.   d1 = d1 * d2;

  68.   }

  69.   nums.add(i, d1);

  70.   i--;

  71.   }

  72.   }

  73.   while (!opts.isEmpty()) {

  74.   char opt = opts.remove(0);

  75.   double d1 = nums.remove(0);

  76.   double d2 = nums.remove(0);

  77.   if (opt == '+') {

  78.   d1 = d1 + d2;

  79.   } else {

  80.   d1 = d1 - d2;

  81.   }

  82.   nums.add(0, d1);

  83.   }

  84.   return formatNum(nums.get(0));

  85.   }

  86.   /**

  87.   * 获得一个表达式中所有的运算符

  88.   * @param exp

  89.   * @return

  90.   */

  91.   private static List getOptions(String exp) {

  92.   List opts = new ArrayList();

  93.   StringTokenizer st = new StringTokenizer(exp, "@.0123456789");

  94.   while (st.hasMoreTokens()) {

  95.   opts.add(st.nextToken().charAt(0));

  96.   }

  97.   return opts;

  98.   }

  99.   /**

  100.   * 获得一个表达式中所有的数字

  101.   * @param exp

  102.   * @return

  103.   */

  104.   private static List getNums(String exp) {

  105.   List nums = new ArrayList();

  106.   StringTokenizer st = new StringTokenizer(exp, "+-×÷");

  107.   while (st.hasMoreTokens()) {

  108.   String num = st.nextToken();

  109.   if (num.contains("@")) {

  110.   num = "-" + num.substring(1);

  111.   }

  112.   nums.add(Double.parseDouble(num));

  113.   }

  114.   return nums;

  115.   }

  116.   /**

  117.   * 格式一个浮点数

  118.   * @param num

  119.   * @return

  120.   */

  121.   public static String formatNum(double num) {

  122.   DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();

  123.   df.applyLocalizedPattern("#0.##########");

  124.   if (num > 1000000000) {

  125.   df.applyPattern("#0.#######E0");

  126.   }

  127.   return df.format(num);

  128.   }

  129.   /**

  130.   * 格式化表达式

  131.   * 1.替换操作(找出负号,并将其替换成@符号)

  132.   * 2.避免非法表达式的出现

  133.   */

  134.   private static String formatExp(String exp) {

  135.   // 如果表达式是以运算符结束的,则将最后一位运算符去除

  136.   if (exp.matches(".*[+-/×÷]")) {

  137.   exp = exp.substring(0, exp.length() - 1);

  138.   }

  139.   String res = exp;

  140.   if (exp.charAt(0) == '-') {

  141.   res = "@" + res.substring(1);

  142.   }

  143.   for (int i = 1; i < res.length(); i++) {

  144.   if (res.charAt(i) == '-' && (res.charAt(i - 1) == '÷' || res.charAt(i - 1) == '×')) {

  145.   res = res.substring(0, i) + "@" + res.substring(i + 1);

  146.   }

  147.   }

  148.   return res;

  149.   }

  150.   /**

  151.   * 检查表达式是否有括号,并且检查是否符合

  152.   * @param exp

  153.   * @return

  154.   */

  155.   public static boolean checkExp(String exp) {

  156.   boolean res = true;

  157.   int index = exp.indexOf("(");

  158.   if (index != -1) {

  159.   int leftN = 0;

  160.   for (int i = index; i < exp.length(); i++) {

  161.   if (exp.charAt(i) == '(') {

  162.   leftN++;

  163.   }

  164.   else if (exp.charAt(i) == ')') {

  165.   leftN--;

  166.   if (leftN == -1) {

  167.   res = false;

  168.   break;

  169.   }

  170.   }

  171.   }

  172.   if (leftN > 0) {

  173.   res = false;

  174.   }

  175.   }

  176.   return res;

  177.   }

  178.   }
复制代码


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

联系我们

电话:400-654-7778
交流群:523516910

点击咨询

学习资料

千锋教育

订阅|小黑屋|手机版|千锋教育论坛 ( 京ICP备12003911号-3

GMT+8, 20-4-1 00:11 , Processed in 0.317957 second(s), 42 queries .

Powered by 千锋教育 X3.2

© 2001-2015

快速回复 返回顶部 返回列表