JAVA - Как преобразовать входные данные Jtextfield в математическое уравнение, разрешенное моей программой? [Дубликат]

Swift

Есть тонны и тонны объяснений здесь и вокруг StackOverflow, но если вы новичок, просто пытающийся получить что-то основное для работы, попробуйте посмотреть этот учебник YouTube (это помогло мне, наконец, понять, как это сделать).

Передача данных вперед к следующему контроллеру View

Ниже приведен пример, основанный на видео. Идея состоит в том, чтобы передать строку из текстового поля в First View Controller на метку в Second View Controller.

Создать раскладку раскладки в Interface Builder.

First View Controller

Код для первого контроллера просмотра -

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // get a reference to the second view controller
        let secondViewController = segue.destination as! SecondViewController

        // set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    }

}

Контроллер второго взгляда

И код для второго контроллера просмотра -

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    }

}

Не забывайте

  • Крючок (f5) и UILabel.
  • Установите первый и второй контроллеры просмотра в соответствующие файлы Swift в IB.

Передача данных назад к предыдущему контроллеру View

Чтобы передать данные с второго контроллера представления на первый контроллер представления, вы используете протокол и делегат . Этот видеоролик - очень четкая прогулка по этому процессу:

Ниже приведен пример, основанный на видео (с некоторыми изменениями).

Создайте раскладной план в Interface Builder. Опять же, чтобы сделать segue, вы просто управляете перетаскиванием с кнопки на второй контроллер просмотра. Установите идентификатор segue на showSecondViewController. Кроме того, не забудьте подключить выходы и действия, используя имена в следующем коде.

First View Controller

Код для первого контроллера просмотра -

import UIKit

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showSecondViewController" {
            let secondViewController = segue.destination as! SecondViewController
            secondViewController.delegate = self
        }
    }

    func userDidEnterInformation(info: String) {
        label.text = info
    }
}

Обратите внимание на использование нашего пользовательского протокола DataEnteredDelegate.

Второй просмотр контроллера и протокола

Код для второго контроллера просмотра -

import UIKit

// protocol used for sending data back
protocol DataEnteredDelegate: class {
    func userDidEnterInformation(info: String)
}

class SecondViewController: UIViewController {

    // making this a weak variable so that it won't create a strong reference cycle
    weak var delegate: DataEnteredDelegate? = nil

    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) {

        // call this method on whichever class implements our delegate protocol
        delegate?.userDidEnterInformation(info: textField.text!)

        // go back to the previous view controller
        _ = self.navigationController?.popViewController(animated: true)
    }
}

Обратите внимание, что protocol находится вне класса View Controller.

Вот и все. Запустив приложение, вы сможете отправлять данные с второго контроллера представления на первый.

263
задан Francesco Menzani 20 September 2015 в 14:17
поделиться

24 ответа

С JDK1.6 вы можете использовать встроенный механизм Javascript.

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class Test {
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine engine = mgr.getEngineByName("JavaScript");
    String foo = "40+2";
    System.out.println(engine.eval(foo));
    } 
}
321
ответ дан Abdull 5 September 2018 в 10:59
поделиться
171
ответ дан Boann 5 September 2018 в 10:59
поделиться

Кажется, что JEP должен выполнить задание

5
ответ дан Bozho 5 September 2018 в 10:59
поделиться
7
ответ дан Brad Parks 5 September 2018 в 10:59
поделиться

Попробуйте использовать следующий пример кода, используя Javascript-механизм JDK1.6 с обработкой ввода кода.

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class EvalUtil {
private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
public static void main(String[] args) {
    try {
        System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || 5 >3 "));
        System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || true"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public Object eval(String input) throws Exception{
    try {
        if(input.matches(".*[a-zA-Z;~`#$_{}\\[\\]:\\\\;\"',\\.\\?]+.*")) {
            throw new Exception("Invalid expression : " + input );
        }
        return engine.eval(input);
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
 }
}
2
ответ дан Bruce 5 September 2018 в 10:59
поделиться

Я думаю, что когда-либо вы это сделаете, это будет связано с множеством условных утверждений. Но для отдельных операций, например, в ваших примерах, вы можете ограничить это до 4 операторов с чем-то вроде

String math = "1+4";

if (math.split("+").length == 2) {
    //do calculation
} else if (math.split("-").length == 2) {
    //do calculation
} ...

. Это становится намного сложнее, если вы хотите иметь дело с несколькими операциями типа «4 + 5 * 6 ".

Если вы пытаетесь построить калькулятор, я бы перегружал каждую секцию вычисления отдельно (каждый номер или оператор), а не как одну строку.

5
ответ дан BruteForce 5 September 2018 в 10:59
поделиться

Это фактически дополняет ответ, данный @Boann. У этого есть небольшая ошибка, которая вызывает «-2 ^ 2», чтобы дать ошибочный результат -4.0. Проблема для этого - точка, в которой в его оценке оценивается степень возведения в степень. Просто переместите экспоненцию в блок parseTerm (), и все будет хорошо. Посмотрите ниже, что @ Ответ Боанна слегка изменен. Модификация содержится в комментариях.

public static double eval(final String str) {
    return new Object() {
        int pos = -1, ch;

        void nextChar() {
            ch = (++pos < str.length()) ? str.charAt(pos) : -1;
        }

        boolean eat(int charToEat) {
            while (ch == ' ') nextChar();
            if (ch == charToEat) {
                nextChar();
                return true;
            }
            return false;
        }

        double parse() {
            nextChar();
            double x = parseExpression();
            if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
            return x;
        }

        // Grammar:
        // expression = term | expression `+` term | expression `-` term
        // term = factor | term `*` factor | term `/` factor
        // factor = `+` factor | `-` factor | `(` expression `)`
        //        | number | functionName factor | factor `^` factor

        double parseExpression() {
            double x = parseTerm();
            for (;;) {
                if      (eat('+')) x += parseTerm(); // addition
                else if (eat('-')) x -= parseTerm(); // subtraction
                else return x;
            }
        }

        double parseTerm() {
            double x = parseFactor();
            for (;;) {
                if      (eat('*')) x *= parseFactor(); // multiplication
                else if (eat('/')) x /= parseFactor(); // division
                else if (eat('^')) x = Math.pow(x, parseFactor()); //exponentiation -> Moved in to here. So the problem is fixed
                else return x;
            }
        }

        double parseFactor() {
            if (eat('+')) return parseFactor(); // unary plus
            if (eat('-')) return -parseFactor(); // unary minus

            double x;
            int startPos = this.pos;
            if (eat('(')) { // parentheses
                x = parseExpression();
                eat(')');
            } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
                while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
                x = Double.parseDouble(str.substring(startPos, this.pos));
            } else if (ch >= 'a' && ch <= 'z') { // functions
                while (ch >= 'a' && ch <= 'z') nextChar();
                String func = str.substring(startPos, this.pos);
                x = parseFactor();
                if (func.equals("sqrt")) x = Math.sqrt(x);
                else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
                else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
                else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
                else throw new RuntimeException("Unknown function: " + func);
            } else {
                throw new RuntimeException("Unexpected: " + (char)ch);
            }

            //if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation -> This is causing a bit of problem

            return x;
        }
    }.parse();
}
2
ответ дан Community 5 September 2018 в 10:59
поделиться

Вы можете легко оценивать выражения, если ваше приложение Java уже обращается к базе данных без использования каких-либо других JAR.

Некоторые базы данных требуют, чтобы вы использовали фиктивную таблицу (например, «двойную» таблицу Oracle) и другие позволит вам оценивать выражения без «выбора» из любой таблицы.

Например, в Sql Server или Sqlite

select (((12.10 +12.0))/ 233.0) amount

и в Oracle

select (((12.10 +12.0))/ 233.0) amount from dual;

Преимущество использования БД состоит в том, что вы можете одновременно оценить множество выражений. Кроме того, большинство БД позволит вам использовать очень сложные выражения и также будет иметь ряд дополнительных функций, которые можно назвать необходимыми.

Однако производительность может пострадать, если много отдельных выражений нужно оценивать индивидуально, особенно когда БД находится на сетевом сервере.

Ниже рассматриваются проблемы производительности в некоторой степени, используя базу данных Sqlite in-memory.

Вот полный рабочий пример в Java

Class. forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount");
rs.next();
System.out.println(rs.getBigDecimal(1));
stat.close();
conn.close();

Конечно, вы могли бы расширить вышеупомянутый код, чтобы обрабатывать несколько вычислений одновременно.

ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");
12
ответ дан DAB 5 September 2018 в 10:59
поделиться
import java.util.*;
StringTokenizer st;
int ans;

public class check { 
   String str="7 + 5";
   StringTokenizer st=new StringTokenizer(str);

   int v1=Integer.parseInt(st.nextToken());
   String op=st.nextToken();
   int v2=Integer.parseInt(st.nextToken());

   if(op.equals("+")) { ans= v1 + v2; }
   if(op.equals("-")) { ans= v1 - v2; }
   //.........
}
1
ответ дан developer033 5 September 2018 в 10:59
поделиться

Можно преобразовать любую строку выражения в нотации infix в постфиксную нотацию, используя алгоритм shing-yard Джикстры . Результат алгоритма затем может служить входом в постфиксный алгоритм с возвратом результата выражения.

Здесь я написал статью об этом , с реализацией в java

1
ответ дан Emmanuel John 5 September 2018 в 10:59
поделиться

Еще один способ - использовать Spring Expression Language или SpEL, который делает намного больше, а также оценивает математические выражения, поэтому может немного переборщить. Вам не нужно использовать Spring framework для использования этой библиотеки выражений, поскольку она является автономной. Копирование примеров из документации SpEL:

ExpressionParser parser = new SpelExpressionParser();
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2 
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); //24.0

Ниже приведены более сжатые примеры Spel здесь и полные документы здесь

6
ответ дан Faheem Sohail 5 September 2018 в 10:59
поделиться

Правильный способ решить это с помощью lexer и синтаксического анализатора . Вы можете написать простые версии из них самостоятельно, или эти страницы также имеют ссылки на Java-лексеры и парсеры.

Создание рекурсивного синтаксического анализа является хорошим упражнением.

25
ответ дан Greg Hewgill 5 September 2018 в 10:59
поделиться

Для моего университетского проекта я искал анализатор / оценщик, поддерживающий как основные формулы, так и более сложные уравнения (особенно повторяющиеся операторы). Я нашел очень хорошую библиотеку с открытым исходным кодом для JAVA и .NET под названием mXparser.

http://mathparser.org/ / g4]

http://mathparser.org/mxparser-tutorial/

http://mathparser.org/api/

И несколько примеров

1 - Простая механика

Expression e = new Expression("( 2 + 3/4 + sin(pi) )/2");
double v = e.calculate()

2 - Пользовательские аргументы и константы

Argument x = new Argument("x = 10");
Constant a = new Constant("a = pi^2");
Expression e = new Expression("cos(a*x)", x, a);
double v = e.calculate()

3 - Пользователь определенные функции

Function f = new Function("f(x, y, z) = sin(x) + cos(y*z)");
Expression e = new Expression("f(3,2,5)", f);
double v = e.calculate()

4 - Итерация

Expression e = new Expression("sum( i, 1, 100, sin(i) )");
double v = e.calculate()

С наилучшими пожеланиями

9
ответ дан HoldOffHunger 5 September 2018 в 10:59
поделиться

Как насчет чего-то вроде этого:

String st = "10+3";
int result;
for(int i=0;i<st.length();i++)
{
  if(st.charAt(i)=='+')
  {
    result=Integer.parseInt(st.substring(0, i))+Integer.parseInt(st.substring(i+1, st.length()));
    System.out.print(result);
  }         
}

и выполните аналогичные действия для каждого другого математического оператора соответственно.

1
ответ дан keyser 5 September 2018 в 10:59
поделиться

Вы можете взглянуть на структуру Symja :

ExprEvaluator util = new ExprEvaluator(); 
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30" 

Обратите внимание, что можно определить более сложные выражения:

// D(...) gives the derivative of the function Sin(x)*Cos(x)
IAST function = D(Times(Sin(x), Cos(x)), x);
IExpr result = util.evaluate(function);
// print: Cos(x)^2-Sin(x)^2
3
ответ дан Laurent Magnin 5 September 2018 в 10:59
поделиться

Для запуска javascript можно использовать внешнюю библиотеку, такую ​​как RHINO или NASHORN. И javascript может оценивать простую формулу без парсинга строки. Не влияет на производительность, если код написан хорошо. Ниже приведен пример с RHINO -

public class RhinoApp {
    private String simpleAdd = "(12+13+2-2)*2+(12+13+2-2)*2";

public void runJavaScript() {
    Context jsCx = Context.enter();
    Context.getCurrentContext().setOptimizationLevel(-1);
    ScriptableObject scope = jsCx.initStandardObjects();
    Object result = jsCx.evaluateString(scope, simpleAdd , "formula", 0, null);
    Context.exit();
    System.out.println(result);
}
1
ответ дан Manish 5 September 2018 в 10:59
поделиться

Вы также можете попробовать интерпретатор BeanShell :

Interpreter interpreter = new Interpreter();
interpreter.eval("result = (7+21*6)/(32-27)");
System.out.println(interpreter.get("result"));
12
ответ дан marciowerner 5 September 2018 в 10:59
поделиться

Класс Java, который может оценивать математические выражения:

package test;

public class Calculator {

    public static Double calculate(String expression){
        if (expression == null || expression.length() == 0) {
            return null;
        }
        return calc(expression.replace(" ", ""));
    }
    public static Double calc(String expression) {

        if (expression.startsWith("(") && expression.endsWith(")")) {
            return calc(expression.substring(1, expression.length() - 1));
        }
        String[] containerArr = new String[]{expression};
        double leftVal = getNextOperand(containerArr);
        expression = containerArr[0];
        if (expression.length() == 0) {
            return leftVal;
        }
        char operator = expression.charAt(0);
        expression = expression.substring(1);

        while (operator == '*' || operator == '/') {
            containerArr[0] = expression;
            double rightVal = getNextOperand(containerArr);
            expression = containerArr[0];
            if (operator == '*') {
                leftVal = leftVal * rightVal;
            } else {
                leftVal = leftVal / rightVal;
            }
            if (expression.length() > 0) {
                operator = expression.charAt(0);
                expression = expression.substring(1);
            } else {
                return leftVal;
            }
        }
        if (operator == '+') {
            return leftVal + calc(expression);
        } else {
            return leftVal - calc(expression);
        }

    }

    private static double getNextOperand(String[] exp){
        double res;
        if (exp[0].startsWith("(")) {
            int open = 1;
            int i = 1;
            while (open != 0) {
                if (exp[0].charAt(i) == '(') {
                    open++;
                } else if (exp[0].charAt(i) == ')') {
                    open--;
                }
                i++;
            }
            res = calc(exp[0].substring(1, i - 1));
            exp[0] = exp[0].substring(i);
        } else {
            int i = 1;
            if (exp[0].charAt(0) == '-') {
                i++;
            }
            while (exp[0].length() > i && isNumber((int) exp[0].charAt(i))) {
                i++;
            }
            res = Double.parseDouble(exp[0].substring(0, i));
            exp[0] = exp[0].substring(i);
        }
        return res;
    }


    private static boolean isNumber(int c) {
        int zero = (int) '0';
        int nine = (int) '9';
        return (c >= zero && c <= nine) || c =='.';
    }

    public static void main(String[] args) {
        System.out.println(calculate("(((( -6 )))) * 9 * -1"));
        System.out.println(calc("(-5.2+-5*-5*((5/4+2)))"));

    }

}
0
ответ дан MultiplyByZer0 5 September 2018 в 10:59
поделиться

, если мы собираемся его реализовать, мы можем использовать приведенный ниже алгоритм: -

  1. Пока еще есть токены для чтения, 1.1. Получите следующий токен. 1.2 Если токен: 1.2.1 Число: нажмите на стек значений. 1.2.2. Переменная: получить ее значение и нажать на стек значений. 1.2.3 Левая скобка: надавите на стек оператора. 1.2.4 Правильная скобка:
     1 While the thing on top of the operator stack is not a 
       left parenthesis,
         1 Pop the operator from the operator stack.
         2 Pop the value stack twice, getting two operands.
         3 Apply the operator to the operands, in the correct order.
         4 Push the result onto the value stack.
     2 Pop the left parenthesis from the operator stack, and discard it.
    
    1.2.5 Оператор (назовите его thisOp):
     1 While the operator stack is not empty, and the top thing on the
       operator stack has the same or greater precedence as thisOp,
       1 Pop the operator from the operator stack.
       2 Pop the value stack twice, getting two operands.
       3 Apply the operator to the operands, in the correct order.
       4 Push the result onto the value stack.
     2 Push thisOp onto the operator stack.
    
  2. Пока стек оператора не пуст, 1 Выполните посылку оператора из стека оператора. 2 Выполните дважды стек значений, получив два операнда. 3 Примените оператор к операндам в правильном порядке. 4 Нажмите результат в стек значений.
  3. В этот момент стек оператора должен быть пустым, а стек значений должен иметь только одно значение, которое является конечным результатом.
5
ответ дан Prashant Gautam 5 September 2018 в 10:59
поделиться

Слишком поздно, чтобы ответить, но я столкнулся с такой же ситуацией, чтобы оценить выражение в java, это может помочь кому-то

MVEL выполнять вычисления времени выполнения, мы можем написать java-код в String чтобы получить его в этом.

    String expressionStr = "x+y";
    Map<String, Object> vars = new HashMap<String, Object>();
    vars.put("x", 10);
    vars.put("y", 20);
    ExecutableStatement statement = (ExecutableStatement) MVEL.compileExpression(expressionStr);
    Object result = MVEL.executeExpression(statement, vars);
1
ответ дан Saravana 5 September 2018 в 10:59
поделиться

Это еще одна интересная альтернатива https://github.com/Shy-Ta/expression-evaluator-demo

. Использование очень простое и выполняет задание, например:

  ExpressionsEvaluator evalExpr = ExpressionsFactory.create("2+3*4-6/2");  
  assertEquals(BigDecimal.valueOf(11), evalExpr.eval()); 
6
ответ дан Scorpion 5 September 2018 в 10:59
поделиться

Еще один вариант: https://github.com/stefanhaustein/expressionparser

Я применил это, чтобы иметь простой, но гибкий вариант, позволяющий обоим:

Связанный выше TreeBuilder является частью демонстрационного пакета CAS , который выполняет символический вывод. Существует также пример BASIC-интерпретатора , и я начал использовать интерпретатор TypeScript , используя его.

1
ответ дан Stefan Haustein 5 September 2018 в 10:59
поделиться
2
ответ дан Taher Khorshidi 5 September 2018 в 10:59
поделиться

ЗДЕСЬ - это другая библиотека с открытым исходным кодом на GitHub с именем EvalEx.

В отличие от механизма JavaScript эта библиотека ориентирована только на оценку математических выражений. Кроме того, библиотека расширяема и поддерживает использование логических операторов, а также круглых скобок.

15
ответ дан Tanvir 5 September 2018 в 10:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: