开发者

Implement modulo operator in calculator program

开发者 https://www.devze.com 2023-01-24 16:57 出处:网络
Here is my code so far: public class Token { // Data: private String type = \"\"; private String name = \"\";

Here is my code so far:

public class Token {
        // Data:
        private String type = "";
        private String name = "";
        private double value = 0;

        // Constructors:
        public Token() { this( "" ); }
        public Token( String t ) { this( t, 0 ); }
        public Token( String t, double v ) { this( t, t, v ); }
        public Token( String t, String n, double v ) { 
            type = t; name = n; value = v; 
        }

        // Methods:
        public String getType( ) { return type;}
        public String getName( ) { return name;}
        public double getValue( ) { return value; }
        public String toString( ) { return (" type="+type+" name="+name+" value="+value);}
}
import java.util.*;

public class Memory {

    private HashMap<String, Double> map;

    /** Creates new Memory */
    public Memory() {
        map = new HashMap<String, Double>();
    }

    public void store(String name, double value) {
        map.put(name, new Double(value));
    }

    public double fetch(String name) {
        Double x = (Double)map.get(name);
        if (x == null) return 0;
        return x.doubleValue();
    } 
}

public class Evaluator {
    private double value;
    private static EvalTokenizer str; 
    private static Memory mem = new Memory();

    public Evaluator( String s ) {
        str = new EvalTokenizer( s );
        value = evaluate();    
    }

    public double getValue() {
        return value;
    }
    public void storeCurrentValue(int line) {
        mem.store("$"+line, value);
    }
    private double evaluate() {
        return evalStatement(str.getToken());
    }

    private double evalStatement(Token firstToken) {
        /* <statement> ::= <var> = <expression> 
                         | <expression> 
                         */
        String s = firstToken.getType();
        // if (s.equals("goto")) return 0;
        if (s.equals("_id") && (str.peekToken().getType()).equals("=")) {
            // <statement> ::= <var> = <expression> 
            str.getToken();
            double x = evalExpression(str.getToken());
            mem.store(firstToken.getName(), x);
            return x;
        }
        return evalExpression(firstToken);
    }

    private double evalExpression(Token firstToken) {
        /* <expression> ::= <term> 
                          | <expression> + <term>
                          | <expression> - <term>
        */
        double x = evalTerm(firstToken);
        while (true) {
            String op = str.peekToken().getType();
            if (op.equals("+") || op.equals("-")) {
                str.getToken(); // skip "+" or "-"
                double y = evalTerm(str.getToken());
                if (op.equals("+")) x += y;
                else x -= y;
            } else
                return x;
        }
    }

    private double evalTerm(Token firstToken) {
        /* <term> ::= <factor>
                    | <term> * <factor> 
                    | <term> / <factor> 
        */
        double x = evalFactor(firstToken);
        while (true) {
            String op = str.peekToken().getType();
            if (op.equals("*") || op.equals("/") {
                str.getToken(); // skip "*" or "/"
                double y = evalFactor(str.getToken());
                if (op.equals("*")) x = x*y;
                else x= x/y;

            } else return x;


        }
    }

    private double evalFactor(Token firstToken) {
        /* <factor> ::= ( <expression> )
                    | + <factor>
                    | - <factor>
                    | <variable>  
                    | ++ <variable>  
                    | -- <variable>
                    | <number> 
        */
        String t = firstToken.getType();

        if (t.equals("(")) { 
            // <factor> ::= ( <expression> )
            double x = evalExpression(str.getToken());
            String nex = str.getToken().getType();
            if (!nex.equals(")")) throw new ArithmeticException("bad expression" );
            return x;
        }

        // <factor> ::= + <factor> | - <factor>
        if (t.equals("+")) return (evalFactor(str.getToken()));
        if (t.equals("-")) return (-evalFactor(str.getToken()));

        // <factor> ::= <number> 
        if (t.equals("_num")) return firstToken.getValue(); 

        // <factor> ::= <variable> 
        if (t.equals("_id")) return mem.fetch(firstToken.getName());

        if (t.equals("++") || t.equals("--")) { 
            // <factor> ::= ++ <variable> | -- <variable> 
            firstToken = str.getToken();
            if ((firstToken.getType()).equals("_id")) {
                double x = mem.fetch(firstToken.getName());
                if (t.equals("++")) {
                    mem.store(firstToken.getName(), x+1);
                    return x+1;
                } else {
                    mem.store(firstToken.getName(), x-1);
                    return x-1;
                }
            }
        }

        throw new ArithmeticException("bad expression" );
    }
}
import java.util.StringTokenizer;

public class EvalTokenizer {
    // Data:
    private StringTokenizer str;
    private Token nextToken = new Token();

    public EvalTokenizer( String line ) { 
        str = new StringTokenizer(line, "+*-/().<>!=%,|& ", true);
        getToken();
    }

    public Token peekToken() { return nextToken; }

    /**
     * A token is either a number literal (integer or double), an identifier, or special symbols 
     * getToken finds the next token, skipping blanks, and return it.
     * For _int or _double token, place the processed value in value.
     * For _id, place the name of the identifier in name.
     * Throw ArithmeticException if input is unrecognized.
     */
    public Token getToken( ) throws ArithmeticException {

         static boolean isVariable(String id) {

         }
        Token result = nextToken;
        nextToken = getNextToken();
        String t1 = result.getType();
        String t2 = nextToken.getType();

        // handle floating numbers
        if (t1.equals("_num") && t2.equals(".")) {
            nextToken = getNextToken();
            t2 = nextToken.getType();
            if (!t2.equals("_num")) throw new ArithmeticException("number format error" );
            t2 = nextToken.getName();
            double x = result.getValue()+nextToken.getValue()*Math.pow(10.0, -t2.length());
            nextToken = getNextToken();
            return new Token("_num", "", x);
        }

        if (t1.equals("$")) {
            if (t2.equals("_int")) {        
                double x = nextToken.getValue();
                nextToken = getNextToken();
                return new Token("_dollar", x);
            } else 
                throw new ArithmeticException("dollar variable format error" );
        }

        if (t1.equals("+")) {
            if (t2.equals("+")) { nextToken = getNextToken(); return new Token("++"); }
        }

        if (t1.equals("-")) {
            if (t2.equals("-")) { nextToken = getNextToken(); return new Token("--"); }
        }

        if (t2.equals("=")) { 
            if (t1.equals(">")) { nextToken = getNextToken(); return new Token(">="); }
            if (t1.equals("<")) { nextToken = getNextToken(); return new Token("<="); }
            if (t1.equals("=")) { nextToken = getNextToken(); return new Token("=="); }
        }
        System.out.println("token = "+result);
        return result;
    }

    private Token getNextToken() throws ArithmeticException {
        long theValue;    
        // Return a default empty token when no more tokens in str.
        if( !str.hasMoreTokens()) return new Token();  

        String s = str.nextToken( );
        if( s.equals( " " ) ) return getNextToken();

        char c = s.charAt(0);
        if ('0' <= c && c <= '9') {  // numbers
            try { theValue = Long.parseLong( s ); }
            catch( NumberFormatException e ) {
                throw new ArithmeticException("number format error" );
            }
            return new Token( "_num", s, theValue);
        } 

        if ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '$') // identifiers
            return new Token( "_id", s, 0);

        return new Token( s, s, 0 );
    }

}
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Calculator {
    /**
     * Simple main to exercise Evaluator class.
     */
    public static void main( String [ ] args )
    {
        String str;
        BufferedReader in = new BufferedReader( new InputStreamReader( System.in ) );
        int line = 1;
        System.out.print( "Enter expressions, one per line:\nline 1: " );

        while (true) {
            try {
                str = in.readLine( );
                if (str == null) continue; 
                if (str.equals("quit")) break;
                Evaluator ev = new Evaluator( str );
                System.out.println( "line " + line + " result >>> " + ev.getValue( ) );
                ev.storeCurrentValue(line);

                line++;
                System.out.print( "line "+line+": " );
            }
            catch( IOException e ) { 
                System.err.println( e );
                System.out.print( "line "+line+": " );
            }
            catch (ArithmeticException e) { 
                System.err.println( e );
                System.out.print( "line "+line+": " );
            }
        } // end while

        System.out.println("Goodbye.");
    } // end main
}

I need to edit this block of the code to implement the % operator:

private double evalTerm(Token firstToken) {
        /* <term> ::= <factor>
                    | <term> * <factor> 
                    | <term> / <factor> 
        */
        double x = evalFactor(firstToken);
        while (true) {
            String op = str.peekToken().getType();
            if (op.equals("*") || op.equals("/") {
                str.getToken(); // skip "*" or "/"
                double y = evalFactor(str.getToken());
                if (op.equals("*")) x = x*y;
                else x= x/y;

            } else return x;


        }
    }

I have tried this, but for some reason it isn't working even though % is part of my tokens:

private double evalTerm(Token firstToken) {
        /* <term> ::= <factor>
                    | <term> * <factor> 
                    | <term> / <factor> 
        */
        double x = evalFactor(firstToken);
        while (true) {
            String op = str.peekToken开发者_如何学Python().getType();
            if (op.equals("*") || op.equals("/") || op.equals("%")) || {
                str.getToken(); // skip "*" or "/"
                double y = evalFactor(str.getToken());
                if (op.equals("*")) x = x*y;
                if (op.equals("/")) x= x/y;
                else x = x%y;
            } else return x;


        }
    }

What am I doing wrong and how can I fix it?


in your code you have

if (op.equals("*")) x = x*y;
if (op.equals("/")) x= x/y;
else x = x%y;

i think you mean to have an else if on the second line ie

if (op.equals("*")) x = x*y;
else if (op.equals("/")) x= x/y;
else x = x%y;


The code below should work for you:

    private double evalTerm(Token firstToken) {
    /* <term> ::= <factor>
                | <term> * <factor> 
                | <term> / <factor> 
                | <term> % <factor> 
    */
    double x = evalFactor(firstToken);
    while (true) {
        String op = str.peekToken().getType();
        if (op.equals("*") || op.equals("/") || op.equals("%")) {
            str.getToken(); // skip "*" or "/"
            double y = evalFactor(str.getToken());
            if (op.equals("*")) { 
                x = x*y; 
            } else if (op.equals("/")) {
                x = x/y;       
            }
            else x= x%y;

        } else return x;


    }
}

There were two issues. Firstly you had a syntax error in the outer if statement. Secondly, the inner if statement had a logic error. Without the else before if (op.equals("/")) it would be match twice for '*' first as x*y and then as x%y giving '(x*y)%y'.


The code works fine for me once all the (four or so) syntax errors are fixed. However, you will want to chain those if statements, otherwise the * operator matches also the % operator:

if (op.equals("*")) x = x * y;
**else** if (op.equals("/")) x = x / y;
else x = x % y;

Here is the output of finding 11 % 4, which is 3 (11 = 2 * 4 + 3).

Enter expressions, one per line:
line 1: 11 % 4
token =  type= name= value=0.0
token =  type=_num name=11 value=11.0
token =  type=% name=% value=0.0
token =  type=_num name=4 value=4.0
line 1 result >>> 3.0
line 2: 
0

精彩评论

暂无评论...
验证码 换一张
取 消