Engine for Calculator by Michael Schmidt : 计算器 « SWT-JFace-Eclipse « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » SWT-JFace-Eclipse » 计算器屏幕截图 
Engine for Calculator by Michael Schmidt

/**
  The following code is from Michael Schmidt(MichaelMSchmidt (at) msn.com).
  
  The code is published under BSD license.
  
  Thanks for the input from Michael Schmidt.
*/


package us.mschmidt.komo;

/**
 * This is a generic calculator engine that includes a memory register, some
 * numeric conversions (square root, inverse), and the ability to chain 
 * calculations.  To use it, create a GUI shell with a display and some means 
 * of entering keystrokes (Buttons work well).  Invoke this engine from the GUI
 * shell using the constructor method, which requires that the display size 
 * (String length) be set.  Obtain the initial display, if desired, with the 
 * getDisplayString() method.  Subsequently, the display string is returned by 
 * the setInput() method when an operation (character) is passed to the engine.
 * <p>
 * The constructor requires a display size to be set.  The minimum is three
 * characters, with at least 22 characters recommended and recommended  size 
 * being 30 characters.  
 *  
 @author   Michael Schmidt
 @version  1.1
 */
class CalcEngine {
  
  // Instantiatee constants
  private final String calcChars;
  private final String convChars;
  private final String dispChars;
  private final String memChars;
  private final String errChars;
  
  // Instantiate variables
  // The error messages
  private String nanErr = new String();
  private String tooLongErr = new String();
  private String infinityErr = new String();
  private int displaySize;
  
  // The calculator 'registers'
  private String displayString = new String();
  private String memoryString = new String();
  private String operatorString = new String();
  
  // A boolean to indicate if display will be cleared on the next key entry
  private boolean clearDisplay;
  
  // A character to store the pending calculation
  private char calcChar;

  /**
   * Constructor to create the calculator engine object.
   
   @param displaySizeVal  The GUI display size, minimum of 3 and
   *                         recommended size of 30
   */
  CalcEngine(final int displaySizeVal) {
    final int minSize = 3;
    // Initialize operation characters
    calcChars = "+-/*=";
    convChars = "IQ";
    dispChars = "BCERS.0123456789";
    memChars = "DLMP";
    errChars = "EINO*";
    
    // Set initial display and internal variables
    displayString = "0.";
    clearDisplay = true;
    calcChar = ' ';
    
    // Set the display size
    displaySize = minSize;
    if (displaySizeVal > minSize) {
      displaySize = displaySizeVal;
    
    // Customize the error strings based on the display size
    setErrorStrings();
  }
  
  /**
   * Customizes the error messages based on the display size.
   */
  private void setErrorStrings() {
    
    // Initialize constants for display size thresholds
    final int infLength = 8;
    final int nanLength = 12;
    final int tooLongLength = 15;
    final int fullLength = 22;
    
    // Set default strings for optimal display size
    nanErr = "Not a Number";
    tooLongErr = "Number too long";
    infinityErr = "Infinity";
    
    if (displaySize < infLength) {
      nanErr = "NaN";
      tooLongErr = "***";
      infinityErr = "Inf";
    else if (displaySize < nanLength) {
      nanErr = "NaN";
      tooLongErr = "Overflow";
    else if (displaySize < tooLongLength) {
      tooLongErr = "Overflow";
    else if (displaySize >= fullLength) {
      nanErr = "ERROR: " + nanErr;
      tooLongErr = "ERROR: " + tooLongErr; 
      infinityErr = "ERROR: " + infinityErr; 
    }
  }
  
  /**
   * Provides the display string to the calling class.  Used after the  
   * engine is instantiated.  Subsequently, the display string is returned by
   * the setInput() method.
   
   @return  the display String
   */
  public String getDisplayString() {
    return displayString;
  }
  
  /**
   * Allows entry of keystrokes from the calling class.
   
   @param keyVal  A designation of the key pressed by the user using the
   *                 code.  
   *                 Display codes: B backspace, C clear, E clear entry,
   *                 R recall memory to display, S change sign, . decimal, 
   *                 0-9 numeric entries.
   *                 Memory codes: D clear memory, M subtract from memory, 
   *                 L store in memory, P add to memory. 
   *                 Calculate codes: I inverse, Q square root, S subtract.
   @return        boolean true if the display has changed, false if not
   */
  public String setInput(final char keyVal) {
    final char keyChar = keyVal;
    if (dispChars.indexOf(keyChar!= -1) {
      doDisplayOp(keyChar);
    else if (convChars.indexOf(keyChar!= -1) {
      doConvertOp(keyChar);
    else if (memChars.indexOf(keyChar!= -1) {
      doMemoryOp(keyChar);
    else if (calcChars.indexOf(keyChar!= -1) {
      doCalcOp(keyChar);
    }
    return displayString;
  }
  
  /**
   * Clears the display when 1) the clearDisplay flag had previously been set
   * to 'true' and 2) a new character or calculation operation is entered.
   */
  private void doDisplayClear() {
    if (clearDisplay) {
      displayString = "";
      clearDisplay = false;
    }
  }

  /**
   * Performs number conversion operations: inverse (1/X) and square root.
   
   @param keyVal  a designation of the key pressed by the user
   */
  private void doConvertOp(final char keyVal) {
    final char opChar = keyVal;
    String tempString = doConvert(displayString, opChar);
    clearDisplay = true;
    if (tempString.length() 0) {
      displayString = tempString;
    }
  }

  /**
   * Performs display operations.  Simple assignment operations are performed 
   * in this method while more complex operations are performed in sub-methods. 
   
   @param keyVal  a designation of which key was pressed by the user
   */
  private void doDisplayOp(final char keyVal) {
    final char opChar = keyVal;

    switch (opChar) {
      case 'B':  // Backspace
        doBackspace();
        break;

      case 'C':  // Clear.  Note use of dropthrough
        operatorString = "";
        calcChar = ' ';

      case 'E':  // Clear Entry
        displayString = "0.";
        clearDisplay = true;
        break;


      case 'R':  // Recall Memory to Display
        displayString = memoryString;
        break;

      case 'S':  // Change Sign
        doChangeSign();
        break;

      case '.':  // Can't have two decimal points.
        doDecimal(opChar);
        break;

      case '0':  // Don't want 00 to be entered.
        doZero(opChar);
        break;

      default:  // Default case is for the digits 1 through 9.
        doAddChar(opChar);
        break;
    }
  }
  
  /**
   * Performs backspace operation.
   */
  private void doBackspace() {
    if (isError(displayString)) {
      return;
    }
    if (displayString.length() 0) {
      displayString = displayString.substring(
          0, displayString.length() 1);
    }
  }

  /**
   * Performs operation to add a character to the display.
   
   @param c  the character to add
   */
  private void doAddChar(final char c) {
    if (isError(displayString)) {
      return;
    }
    if (displayString.length() < displaySize) {
      doDisplayClear();
      displayString += c;
    }
  }
  
  /**
   * Performs sign change operation.
   */
  private void doChangeSign() {
    if (isError(displayString)) {
      return;
    }
    if ('-' == displayString.charAt(0)) {
      displayString = displayString.substring(
          1, displayString.length());
    else if (displayString.length() < displaySize) {
      displayString = '-' + displayString;
    }
  }
  
  /**
   * Performs operation when decimal is pressed.
   
   @param c  the decimal character
   */
  private void doDecimal(final char c) {
    if (isError(displayString)) {
      return;
    }
    if (displayString.indexOf('.'== -
        && displayString.length() < displaySize) {
      doDisplayClear();
      displayString += c;
    }
  }
  
  /**
   * Performs operation when '0' is pressed.
   
   @param c  the zero operation character
   */
  private void doZero(final char c) {
    if (isError(displayString)) {
      return;
    }
    if (!displayString.equals("0"&& displayString.length() <  displaySize) {
      doDisplayClear();
      displayString += c;
    }
  }

  /**
   * Updates the value stored in the memory register.  Simple assignment 
   * operations are performed here while more complex operations are performed 
   * in sub-methods.
   
   @param keyVal  a designation of which key was pressed by the user
   */
  private void doMemoryOp(final char keyVal) {
    final char opChar = keyVal;

    switch (opChar) {
      case 'D':  // Clear Memory
        memoryString = "";
        break;
        
      case 'L':  // Save to Memory
        assignMemoryString(trimString(displayString));
        break;

      case 'M':  // Subtract from Memory
        subtractFromMemory();
        break;

      case 'P':  // Add to Memory
        addToMemory();
        break;

      default:  // Do nothing - this should never happen.
        break;
    }

    clearDisplay = true;
  }
  
  /**
   * Performs the operation to add a display entry to the number in the
   * memory register.
   */
  private void addToMemory() {
    String tempString = new String();
    if (== memoryString.length()) {
      tempString = trimString(displayString);
    else {
      tempString = doComputation(memoryString, displayString, '+');
    }
    assignMemoryString(tempString);
  }
  
  /**
   * Performs the operation to subtract a display entry from the number in the
   * memory register.
   */
  private void subtractFromMemory() {
    String tempString = new String();
    if (== memoryString.length()) {
      tempString = doComputation("0", displayString, '-');
    else {
      tempString = doComputation(memoryString, displayString, '-');
    }
    assignMemoryString(tempString);
  }
  
  /**
   * Checks if String is valid and, if so, assigns it to the memory register.
   
   @param s  the String to assign
   */
  private void assignMemoryString(final String s) {
    if (isError(s)) {
      displayString = s;
    else {
      memoryString = s;
    }
  }

  /**
   * Guides 2-number calculations.  Updates the operator string, display 
   * string, and the pending calculation flag.  Performs calculation if 
   * possible.
   
   @param keyVal  a designation of which key was pressed byt he user
   */
  private void doCalcOp(final char keyVal) {
    final char opChar = keyVal;

    // If there is no display value, the keystroke is deemed invalid and 
    // nothing is done.
    if (== displayString.length()) {
      return;
    }

    // If there is no operator value, '=' key presses are considered 
    // invalid.  If a calculation key is pressed, check that the display 
    // value is valid and if so, copy the display value to the operator.  
    // No calculation is done.
    if (== operatorString.length()) {
      if ('=' != opChar) {
        if (isError(displayString)) {
          calcChar = ' ';
        else {
          operatorString = displayString;
          calcChar = opChar;
        }
        clearDisplay = true;
      }
      return;
    }
    
    // There are operator and display values, so do the pending calculation.
    displayString = doComputation(operatorString, displayString, calcChar);

    // If '=' was pressed or result was invalid, reset pending calculation
    // flag and operator value.  Otherwise, set new calculation flag so 
    // calculations can be chained.
    if (('=' == opChar|| isError(displayString)) {
      calcChar = ' ';
      operatorString = "";
    else {
      calcChar = opChar;
      operatorString = displayString;
    }

    // Set the clear display flag
    clearDisplay = true;
  }
  
  /**
   * Performs the computations.
   
   @param numStringA  the displayed value
   @param numStringB  the stored value
   @param opVal        the operation to be performed
   @return            the solution as a string variable
   */
  private String doComputation(final String numStringA, 
      final String numStringB, final char opVal) {
    String valStringA = numStringA;
    String valStringB = numStringB;
    char opChar = opVal;
    Double valA = 0.0
    Double valB = 0.0;
    Double valAnswer = 0.0;

    // Make sure register strings are numbers
    if (valStringA.length() && valStringB.length() 0) {
      try {
        valA = Double.parseDouble(numStringA);
        valB = Double.parseDouble(numStringB);
      catch (final NumberFormatException e) {
        return nanErr;
      }
    else {
      return "";
    }

    switch (opChar) {
      case '+':  // Addition
        valAnswer = valA + valB;
        break;

      case '-':  // Subtraction
        valAnswer = valA - valB;
        break;

      case '/':  // Division
        valAnswer = valA / valB;
        break;

      case '*':  // Multiplication
        valAnswer = valA * valB;
        break;

      default:  // Do nothing - this should never happen
        break;
    }

    // Convert answer to properly formatted string.
    return trimString(valAnswer.toString());
  }
  
  /**
   * Performs number conversion computations.
   
   @param numString  the number to be converted
   @param opVal    designation of the operation to be performed
   @return      the converted value
   */
  private String doConvert(final String numString, final char opVal) {
    char opChar = opVal;
    String valString = numString;
    Double valA = 0.0
    Double valAnswer = 0.0;

    // Make sure String is a number.  If it is zero-length, assume the
    // keystroke was inadvertent and return "".
    if (valString.length() 0) {
      try {
        valA = Double.parseDouble(valString);
      catch (final NumberFormatException e) {
        return nanErr;
      }
    else {
      return "";
    }

    switch (opChar) {
      case 'Q':  // Square Root
        valAnswer = Math.sqrt(valA);
        break;

      case 'I':  // Inverse
        valAnswer = 1.0 / valA;
        break;

      default:  // Do nothing - this should never happen
        break;
    }

    // Return properly formatted result String.
    return trimString(valAnswer.toString());
  }

  /**
   * Formats String to be displayed.
   
   @param stringVal  a new string to be displayed
   @return          the properly formatted and trimmed string
   */
  private String trimString(final String stringVal) {
    String returnString = stringVal;

    // Check if value is Not a Number
    if (returnString.equals("NaN")) {
      return nanErr;
    }
    
    // Check if value is infinity
    if (returnString.endsWith("Infinity")) {
      return infinityErr;
    }
    
    // Check if value is -0
    if (returnString.equals("-0.0")) {
      return "0";
    }
    
    // Trim unnecessary trailing .0
    if (returnString.endsWith(".0")) {
      returnString = returnString.substring(0, returnString.length() 2);
    }
    
    // Check if string is too long to display
    if (returnString.length() > displaySize) {
      return tooLongErr;
    }

    return returnString;
  }
  
  /**
   * Tests if the String is an error message.
   
   @param s  the String to be tested
   @return  boolean true if this is an error message, false if not
   */
  private boolean isError(final String s) {
    String testString = s;
    if (== testString.length()) {
      return false;
    }
    char c = testString.charAt(0);
    return ((errChars.indexOf(c== -1)) false true;
  }

  /**
   * Override to provide useful information when the class toString method is
   * called.
   
   @return  the information String
   @see     java.lang.Object#toString()
   */
  @Override
  public final String toString() {
    return "komo.CalcEngine is the engine portion of the calculator utility";
  }
}


           
       
Related examples in the same category
1. Calculator by Michael SchmidtCalculator by Michael Schmidt
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.