/* * calc2.java * * Public License Agreement: You CANNOT use this program for ANYTHING! * This program is a work-in-progress. The only reason I'm giving it * away (with source) is because I'm a nice guy. You cannot sell it, * and may only look at the code; ANY other use should be consulted * with Particle directly (particle at NO SPAM the particle dot com)! You cannot distribute * it either (in ANY form), you can however redirect people to the site * where you got it (which is probably Particle's site). * * This Agreement is VERY restrictive, and should be respected. This * program is part of Prof.Phreak, which is a commercial product (or will * be one), thus, this agreement means business. The source of the program * (which you can compile under Java) is only here to illustrate some innovative * thinking taken in constructing Prof.Phreak (kind of like an advertisement). * * Now, after scarring you a bit, I just wanted to mention that I'm totally * not responsible for ANYTHING BAD that the program does. However, I take * full responsibility for whatever stuff you like about the program. * (i.e.: If it's bad, don't blame me, if it's good, thank me.) * * Copyright(c) 1998-1999, Particle */ import java.lang.*; import java.awt.*; import java.awt.event.*; import java.applet.*; import java.util.*; import java.math.*; /** * a word calculator class * * @version 2.0b */ public class calc2 extends Applet{ /** * text area for expression */ private TextArea expression = null; /** * text area for the answer */ private TextArea answer = null; /** * clear button */ private Button clear = null; /** * enter button */ private Button enter = null; /** * static arrays of word prepresentation of numbers */ private static String[] numericalWords = {"zero","one","two","three","four", "five","six","seven","eight","nine", "ten","eleven","twelve","thirteen", "fourteen","fifteen","sixteen", "seventeen","eighteen","nineteen", "twenty","thirty","forty","fifty", "sixty","seventy","eighty","ninety", "hundred","thousand","million", "billion","trillion","quadrillion", "quintillion","sextillion","septillion", "octillion","nonillion","decillion", "undecillion","duodecillion","tredecillion", "quattuordecillion","quindecillion", "sexdecillion","septendecillion", "octodecillion","novemdecillion", "vigintillion","negative"}; /* and centillion = 10^303 */ /** * numerical representation of words above. */ private static BigInteger[] numericalNumbers = null; static{ numericalNumbers = new BigInteger[numericalWords.length]; int i,j; for(i=0;i<20;i++) numericalNumbers[i] = BigInteger.valueOf(i); for(j=i;j<=100;j+=10,i++) numericalNumbers[i] = BigInteger.valueOf(j); for(BigInteger bigint = BigInteger.valueOf(1000); i= 0) v.addElement(numericalWords[index]); } } if(result != 0 || (n.equals(BigInteger.valueOf(0)) && divider.equals(BigInteger.valueOf(1000)))){ _writeNumber2Word(result,v); return true; } return false; } /** * evaluate a postfix expression... the resulting value is * the first one in the vector. * * @param v the expression to solve * @return if not null, then a string with error explanation */ private String solvePostFixExpression(Vector v){ Vector stack = new Vector(); Enumeration enum = v.elements(); while(enum.hasMoreElements()){ Object o = enum.nextElement(); if(o instanceof BigInteger){ BigInteger integer = (BigInteger)o; stack.addElement(integer); }else if(o instanceof String){ String string = (String)o; if(stack.isEmpty()) return new String("Empty Stack: Postfix Error"); BigInteger a = (BigInteger)(stack.lastElement()); stack.removeElementAt(stack.size()-1); if(stack.isEmpty()) return new String("Empty Stack: Postfix Error"); BigInteger b = (BigInteger)(stack.lastElement()); stack.removeElementAt(stack.size()-1); if(string.equals("+")) stack.addElement(b.add(a)); else if(string.equals("-")) stack.addElement(b.subtract(a)); else if(string.equals("*")) stack.addElement(b.multiply(a)); else if(string.equals("/")) stack.addElement(b.divide(a)); else return new String("Undefined operation: "+string); }else{ return new String("Internal Error in Postfix Expression"); } } if(stack.isEmpty()) return new String("Stack Underflow"); BigInteger ans = (BigInteger)stack.lastElement(); stack.removeElementAt(stack.size()-1); if(!stack.isEmpty()) return new String("No Answer on Stack"); v.removeAllElements(); v.addElement(ans); return null; } /** * convert an infix expression to post fix * * @param v Vector representing expression which to convert to post-fix * @return if not null, then string explaining the error */ private String infixToPostfix(Vector v){ Vector in = new Vector(); Enumeration v_enum = v.elements(); while(v_enum.hasMoreElements()) in.addElement(v_enum.nextElement()); v.removeAllElements(); Vector stack = new Vector(); Enumeration enum = in.elements(); while(enum.hasMoreElements()){ Object o = enum.nextElement(); if(o instanceof BigInteger){ v.addElement(o); }else if(o instanceof String){ String s = (String)o; if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){ if(stack.isEmpty()) stack.addElement(s); else{ String sp = (String)stack.lastElement(); stack.removeElementAt(stack.size()-1); if(sp.equals("(") || sp.equals(")")){ stack.addElement(sp); stack.addElement(s); }else{ if((sp.equals("+") || sp.equals("-")) && (s.equals("*") || s.equals("/"))){ stack.addElement(sp); stack.addElement(s); }else{ stack.addElement(s); v.addElement(sp); } } } }else if(s.equals("(") || s.equals(")")){ if(s.equals("(")) stack.addElement(s); else if(s.equals(")")){ while(!stack.isEmpty()){ String sp = (String)stack.lastElement(); stack.removeElementAt(stack.size()-1); if(!sp.equals("(")) v.addElement(sp); else break; } } }else return new String("Expression Error"); } } while(!stack.isEmpty()){ v.addElement(stack.lastElement()); stack.removeElementAt(stack.size()-1); } return null; } /** * check the parenthesis within the expression * * @param v Expression to check for correct parenthesis * @return if not null, then string explaining the error */ private String checkParenthesis(Vector v){ Vector stack = new Vector(); Enumeration enum = v.elements(); while(enum.hasMoreElements()){ Object o = enum.nextElement(); if(o instanceof String){ String s = (String)o; if(s.equals("(") || s.equals(")")) if(s.equals("(")) stack.addElement(s); else if(stack.isEmpty()) return new String("Expression Error, parenthesis problem."); else stack.removeElementAt(stack.size()-1); } } if(!stack.isEmpty()) return new String("Expression Error, check parenthesis."); return null; } /** * compute the number * * @param arr Number array * @param n the size * @param bound the bound to use * @return the BigInteger array */ private BigInteger[] computeNumber(BigInteger[] arr,int n,BigInteger bound){ BigInteger tmp; BigInteger number = BigInteger.valueOf(0); for(n--;n >= 0;) if(!((tmp=arr[n]).mod(BigInteger.valueOf(100))).equals(BigInteger.valueOf(0)) || arr[n].equals(BigInteger.valueOf(0))) number = number.add(arr[n--]); else if(bound.compareTo(arr[n]) >= 0){ BigInteger[] res = computeNumber(arr,n,tmp); number = number.add(tmp.multiply(res[0])); n = res[1].intValue(); } else break; BigInteger[] tarr = new BigInteger[2]; tarr[0] = number.equals(BigInteger.valueOf(0)) ? BigInteger.valueOf(1):number; tarr[1] = BigInteger.valueOf(n); return tarr; } /** * computer number * * @param arr bigInteger array * @return a big integer representing the array */ private BigInteger computeNumber(BigInteger[] arr){ int i; BigInteger tmp; BigInteger number = BigInteger.valueOf(0); for(i=arr.length-1;i >= 0;) if(!((tmp=arr[i]).mod(BigInteger.valueOf(100))).equals(BigInteger.valueOf(0)) || tmp.equals(BigInteger.valueOf(0))) number = number.add(arr[i--]); else{ BigInteger[] res = computeNumber(arr,i,tmp); number = number.add(tmp.multiply(res[0])); i = res[1].intValue(); } return number; } /** * given a number in word form, returns the java.lang.Integer * object representing that number. * * @param number A number in string form * @return a BigInteger representing the input number */ private BigInteger convertNumber(String number){ Vector n_vec = new Vector(); StringTokenizer st = new StringTokenizer(number); BigInteger sign = BigInteger.valueOf(1); /* positive */ while(st.hasMoreElements()){ String numb = (String)st.nextElement(); if(numb.equals("negative")) sign = BigInteger.valueOf(-1); else{ int loc = findString(numb); if(loc != -1) n_vec.addElement(numericalNumbers[loc]); } } BigInteger[] array = new BigInteger[n_vec.size()]; n_vec.copyInto(array); return computeNumber(array).multiply(sign); } /** * returns whether this number is numerical or not * * @param n A string to test... * @return a boolean value of whether the parameter is a number */ private boolean isnumerical(String n){ if(findString(n) == -1) return false; return true; } /** * returns expression in numerical form (as a Vector of * numbers, operators, etc...) * * @param expr Expression (in string form) to convert to a vector * @return a Vector representing the expression */ private Vector convertExpression(String expr){ StringTokenizer st = new StringTokenizer(expr); String currentNumber = null; Vector numberVector = new Vector(); while(st.hasMoreElements()){ String elements = (String)st.nextElement(); if(elements.equals("open")){ if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } numberVector.addElement("("); }else if(elements.equals("close")){ if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } numberVector.addElement(")"); }else if(elements.equals("plus")){ if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } numberVector.addElement("+"); }else if(elements.equals("minus")){ if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } numberVector.addElement("-"); }else if(elements.equals("times")){ if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } numberVector.addElement("*"); }else if(elements.equals("divide")){ if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } numberVector.addElement("/"); }else if(isnumerical(elements)){ if(currentNumber == null) currentNumber = new String(); currentNumber += elements + " "; } } if(currentNumber != null){ numberVector.addElement(convertNumber(currentNumber)); currentNumber = null; } return numberVector; } /** * given an expression (in word form), this function * returns the answer (in word form) * * @param expr expression to process * @return string representing the result */ private String processExpression(String expr){ Vector exp_numeric = convertExpression(expr); String result = new String(); Enumeration enum = null; String err = checkParenthesis(exp_numeric); if(err != null) return err; err = infixToPostfix(exp_numeric); if(err != null) return err; err = solvePostFixExpression(exp_numeric); if(err != null) return err; BigInteger tmp = (BigInteger)exp_numeric.elementAt(0); exp_numeric.removeAllElements(); writeNumber2Word(tmp,BigInteger.valueOf(1000),exp_numeric); enum = exp_numeric.elements(); while(enum.hasMoreElements()){ Object o = enum.nextElement(); if(o instanceof BigInteger){ BigInteger integer = (BigInteger)o; result += integer.toString() + " "; }else if(o instanceof String){ String string = (String)o; result += string + " "; } } return result; } /** * create UI, setup buttons, etc. */ public void init(){ expression = new TextArea(); expression.setFont(new Font("Courier",Font.PLAIN,12)); answer = new TextArea(); answer.setFont(new Font("Courier",Font.PLAIN,12)); clear = new Button("Clear"); enter = new Button("Enter"); setLayout(new BorderLayout()); Panel ex = new Panel(); ex.setLayout(new BorderLayout()); ex.add("North",new Label("Expression")); ex.add("South",expression); Panel an = new Panel(); an.setLayout(new BorderLayout()); an.add("North",new Label("Answer")); an.add("South",answer); Panel top = new Panel(); top.setLayout(new BorderLayout()); top.add("North",ex); top.add("South",an); Panel buttons = new Panel(); buttons.add(clear); buttons.add(enter); add("South",buttons); add("North",top); } /** * handle button presses * * @param evt The event * @param what The object * @return whether the event was handled */ public boolean action(Event evt, Object what){ if(evt.target instanceof Button){ Button button = (Button)evt.target; if(button.getLabel().equals(clear.getLabel())){ answer.setText(""); expression.setText(""); return true; }else if(button.getLabel().equals(enter.getLabel())){ answer.setText(processExpression( expression.getText().toLowerCase())); return true; } } return false; } }