Some refactoring, improved help

master
Ondřej Hruška 11 years ago
parent d029078b3f
commit fb69aebb2d
  1. 1
      .~lock.rcalc-doc.odt#
  2. BIN
      rcalc-doc.odt
  3. 4
      src/net/mightypork/calculator/CalculatorBatch.java
  4. 20
      src/net/mightypork/calculator/CalculatorInteractive.java
  5. 2
      src/net/mightypork/calculator/Main.java
  6. 28
      src/net/mightypork/calculator/Tests.java
  7. 5
      src/net/mightypork/rcalc/Tokenizer.java
  8. 27
      src/net/mightypork/rcalc/numbers/Fraction.java

@ -0,0 +1 @@
,ondra,Penguin,29.09.2013 21:06,file:///home/ondra/.config/libreoffice/4;

Binary file not shown.

@ -1,4 +1,4 @@
package net.mightypork.semestralka; package net.mightypork.calculator;
import java.io.File; import java.io.File;
@ -19,7 +19,7 @@ import net.mightypork.rcalc.numbers.Fraction;
*/ */
public class CalculatorBatch implements Runnable { public class CalculatorBatch implements Runnable {
/** Rcalc Session used by the calculator */ /** RCalc Session used by the calculator */
private RCalcSession session = new RCalcSession(); private RCalcSession session = new RCalcSession();
/** File to load the expressions from */ /** File to load the expressions from */

@ -1,4 +1,4 @@
package net.mightypork.semestralka; package net.mightypork.calculator;
import java.io.File; import java.io.File;
@ -17,7 +17,7 @@ import net.mightypork.rcalc.numbers.Fraction;
*/ */
public class CalculatorInteractive implements Runnable { public class CalculatorInteractive implements Runnable {
/** Rcalc Session used by the calculator */ /** RCalc Session used by the calculator */
private RCalcSession session = new RCalcSession(); private RCalcSession session = new RCalcSession();
/** Show results as fractions */ /** Show results as fractions */
@ -42,17 +42,18 @@ public class CalculatorInteractive implements Runnable {
+ "Commands:\n" + "Commands:\n"
+ "\thelp - show this help\n" + "\thelp - show this help\n"
+ "\texit - quit the calculator\n" + "\texit - quit the calculator\n"
+ "\tdebug - toggle debug mode (default off)\n"
+ "\tdecimal - toggle decimal/fractional output\n" + "\tdecimal - toggle decimal/fractional output\n"
+ "\tvars - print a list of variables\n" + "\tvars - print a list of variables\n"
+ "\tdebug - toggle debug mode (default off)\n"
+ "\tutest - perform RCalc unit tests\n"
+ "\tload filename - execute commands from a file\n" + "\tload filename - execute commands from a file\n"
+ "\t\t(Expressions from the file can use/change variables)\n" + "\t\t(Expressions from the file can use/change variables)\n"
+ "\n" + "\n"
+ "Mathematical operations, syntax\n" + "Mathematical operations, syntax\n"
+ "\tSupported: + - * / % ^ ! ( )\n" + "\tSupported: + - * / % ^ ! ( )\n"
+ "\tMultiplication sign can be omitted where it makes sense.\n" + "\tMultiplication sign can be omitted where it makes sense.\n"
+ "\tAlong with fractions, decimal-point format works too.\n"
+ "\tUse 'a/b' syntax to express a fraction.\n" + "\tUse 'a/b' syntax to express a fraction.\n"
+ "\tDecimal-point numbers are supported, too.\n"
+ "\n" + "\n"
+ "Variables\n" + "Variables\n"
+ "\tAssign a variable:\n" + "\tAssign a variable:\n"
@ -91,7 +92,7 @@ public class CalculatorInteractive implements Runnable {
while (!sc.hasNextLine()) {} while (!sc.hasNextLine()) {}
String expr = sc.nextLine().toLowerCase().trim(); String expr = sc.nextLine().toLowerCase().trim();
if (expr.equals("%")) { // repeat last expression if (expr.equals("%")) { // repeat last expression
if (history.size() > 0) { if (history.size() > 0) {
expr = history.get(history.size() - 1); expr = history.get(history.size() - 1);
@ -101,7 +102,10 @@ public class CalculatorInteractive implements Runnable {
continue; continue;
} }
} }
// can't use a switch on strings because of java 6 :(
if (expr.equals("exit")) { // quit if (expr.equals("exit")) { // quit
System.out.println("Exit."); System.out.println("Exit.");
return; return;
@ -109,6 +113,10 @@ public class CalculatorInteractive implements Runnable {
} else if (expr.equals("help")) { // show help } else if (expr.equals("help")) { // show help
System.out.println(helpMessage); System.out.println(helpMessage);
} else if (expr.equals("utest")) { // show help
Runnable r = new Tests();
r.run();
} else if (expr.equals("debug")) { // toggle debug mode } else if (expr.equals("debug")) { // toggle debug mode
if (session.isDebug()) { if (session.isDebug()) {

@ -1,4 +1,4 @@
package net.mightypork.semestralka; package net.mightypork.calculator;
import java.io.File; import java.io.File;

@ -1,4 +1,4 @@
package net.mightypork.semestralka; package net.mightypork.calculator;
import net.mightypork.rcalc.RCalc; import net.mightypork.rcalc.RCalc;
@ -9,13 +9,15 @@ import net.mightypork.rcalc.RCalc;
* *
* @author Ondrej Hruska * @author Ondrej Hruska
*/ */
public class Tests { public class Tests implements Runnable {
/** /**
* Run the tests * Run the tests
*/ */
public static void run() { @Override
public void run() {
System.out.println("--- RCalc Unit Tests ---");
RCalc rc = new RCalc(); RCalc rc = new RCalc();
rc.setDebug(true); rc.setDebug(true);
@ -27,22 +29,18 @@ public class Tests {
"(1-1)(1--1)(1---1)(1----1)(1--+-+-+++--+-+1)(1--+-+-+-+-----1)(5*-1)", // minus, plus "(1-1)(1--1)(1---1)(1----1)(1--+-+-+++--+-+1)(1--+-+-+-+-----1)(5*-1)", // minus, plus
"-(15/2)+(72*43-2)-(12+1)", // minus with parentheses "-(15/2)+(72*43-2)-(12+1)", // minus with parentheses
"+34-(--8+2*+13)", // + at beginning of scope "+34-(--8+2*+13)", // + at beginning of scope
// misc "1000!", // big factorial
"23%(6/5)", "24/4/3", // chained division must go LTR
"53/(5-4-1)", "5-4-1", // subtraction must go LTR
"100!", "5(10+1)(4!3)", // implicit multiplication
"24/4/3", "(1/2)^-2", // inverting a fraction
"(10+1)(15-3)",
"13(55-3/12)^2",
"(1/2)^-2",
"13^(1/2)", // should fail
"(1/2)*(3/4)",
"(1/2)/(3/4)", // compound fraction "(1/2)/(3/4)", // compound fraction
"(1/2)*(3/4)", // fraction multiplication
}; };
//@formatter:on //@formatter:on
for (String expr : testCases) { for (String expr : testCases) {
System.out.println("\n\n###### test case begin ######"); System.out.println("\n\n# Test Case #");
try { try {
System.out.println("IN: " + expr); System.out.println("IN: " + expr);
@ -52,5 +50,7 @@ public class Tests {
} }
} }
System.out.println("--- Unit Tests End ---");
} }
} }

@ -1,7 +1,6 @@
package net.mightypork.rcalc; package net.mightypork.rcalc;
import java.math.BigInteger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -109,11 +108,11 @@ public class Tokenizer implements IDebugable {
if (debug && deepDebug) System.out.println("\nNormalize sequences of '+' and '-'\n" + input); if (debug && deepDebug) System.out.println("\nNormalize sequences of '+' and '-'\n" + input);
// turn '-' to '+-' between numbers // turn '-' to '+-' between numbers
input = input.replaceAll("(?<=[0-9)!])-(?=[0-9])", "+-"); input = input.replaceAll("(?<=[0-9)!])-(?=[0-9.])", "+-");
if (debug && deepDebug) System.out.println("\n'-' to '+-' between numbers\n" + input); if (debug && deepDebug) System.out.println("\n'-' to '+-' between numbers\n" + input);
// convert '-' to '+-1*' in front of non-numbers // convert '-' to '+-1*' in front of non-numbers
input = input.replaceAll("-(?=[^0-9])", "+-1*"); input = input.replaceAll("-(?=[^0-9.])", "+-1*");
if (debug && deepDebug) System.out.println("\n'-' to '+-1*' in front of non-numbers\n" + input); if (debug && deepDebug) System.out.println("\n'-' to '+-1*' in front of non-numbers\n" + input);
// discard useless + signs // discard useless + signs

@ -94,16 +94,29 @@ public class Fraction implements IEvaluableToken {
} }
/**
* Create a fraction with numerator parsed from a string, and 1 as
* denominator.
*
* @param number numerator as string
*/
public Fraction(String number) { public Fraction(String number) {
if(number.contains(".")) {
if (number.matches("[.][0-9]+")) {
number = "0" + number;
}
if (number.matches("-[.][0-9]+")) {
number = "-0" + number.substring(1);
}
if (number.matches("-?[0-9]+[.][0-9]+")) {
String[] parts = number.split("[.]"); String[] parts = number.split("[.]");
try{ try {
if(parts.length != 2) throw new ParseError(""); // for the catch this.numerator = new BigInteger(parts[0] + parts[1]);
this.numerator = new BigInteger(parts[0]+parts[1]);
this.denominator = BigInteger.valueOf(10).pow(parts[1].length()); this.denominator = BigInteger.valueOf(10).pow(parts[1].length());
this.simplify_ip(); this.simplify_ip();
}catch(Exception e) { } catch (Exception e) {
e.printStackTrace();
throw new ParseError("Invalid number format."); throw new ParseError("Invalid number format.");
} }
} else { } else {
@ -270,13 +283,13 @@ public class Fraction implements IEvaluableToken {
return new Fraction(numerator.divide(gcd), denominator.divide(gcd)); return new Fraction(numerator.divide(gcd), denominator.divide(gcd));
} }
/** /**
* Simplify the fraction (in place) * Simplify the fraction (in place)
*/ */
private void simplify_ip() { private void simplify_ip() {
BigInteger gcd = numerator.gcd(denominator); BigInteger gcd = numerator.gcd(denominator);
numerator = numerator.divide(gcd); numerator = numerator.divide(gcd);

Loading…
Cancel
Save