Saya mencoba menulis rutin Java untuk mengevaluasi ekspresi matematika sederhana dari String
nilai-nilai seperti:
"5+3"
"10-40"
"10*3"
Saya ingin menghindari banyak pernyataan if-then-else. Bagaimana saya bisa melakukan ini?
Saya mencoba menulis rutin Java untuk mengevaluasi ekspresi matematika sederhana dari String
nilai-nilai seperti:
"5+3"
"10-40"
"10*3"
Saya ingin menghindari banyak pernyataan if-then-else. Bagaimana saya bisa melakukan ini?
Jawaban:
Dengan JDK1.6, Anda dapat menggunakan mesin Javascript bawaan.
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));
}
}
return (Double) engine.eval(foo);
new javax.script.ScriptEngineManager().getEngineByName("JavaScript") .eval("var f = new java.io.FileWriter('hello.txt'); f.write('UNLIMITED POWER!'); f.close();");
- akan menulis file melalui JavaScript ke (secara default) direktori saat ini program
Saya telah menulis eval
metode ini untuk ekspresi aritmatika untuk menjawab pertanyaan ini. Itu penambahan, pengurangan, perkalian, pembagian, eksponensial (menggunakan ^
simbol), dan beberapa fungsi dasar seperti sqrt
. Ini mendukung pengelompokan menggunakan (
... )
, dan itu membuat operator lebih diutamakan dan aturan associativity .
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 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
return x;
}
}.parse();
}
Contoh:
System.out.println(eval("((4 - 2^3 + 1) * -sqrt(3*3+4*4)) / 2"));
Output: 7.5 (yang benar)
Parser adalah parser keturunan rekursif , sehingga secara internal menggunakan metode parse yang terpisah untuk setiap tingkat prioritas operator dalam tata bahasanya. Saya menyimpannya singkat sehingga mudah untuk dimodifikasi, tetapi berikut adalah beberapa ide yang mungkin ingin Anda kembangkan:
Variabel:
Bit parser yang membaca nama untuk fungsi dapat dengan mudah diubah untuk menangani variabel kustom juga, dengan mencari nama dalam tabel variabel yang diteruskan ke eval
metode, seperti a Map<String,Double> variables
.
Kompilasi dan evaluasi terpisah:
Bagaimana jika, setelah menambahkan dukungan untuk variabel, Anda ingin mengevaluasi ekspresi yang sama jutaan kali dengan variabel yang berubah, tanpa menguraikannya setiap waktu? Itu mungkin. Pertama-tama tentukan antarmuka yang digunakan untuk mengevaluasi ekspresi yang dikompilasi:
@FunctionalInterface
interface Expression {
double eval();
}
Sekarang ubah semua metode yang mengembalikan double
s, jadi alih-alih mereka mengembalikan instance dari antarmuka itu. Sintaks lambda Java 8 sangat cocok untuk ini. Contoh salah satu metode yang diubah:
Expression parseExpression() {
Expression x = parseTerm();
for (;;) {
if (eat('+')) { // addition
Expression a = x, b = parseTerm();
x = (() -> a.eval() + b.eval());
} else if (eat('-')) { // subtraction
Expression a = x, b = parseTerm();
x = (() -> a.eval() - b.eval());
} else {
return x;
}
}
}
Itu membangun pohon Expression
objek rekursif yang mewakili ekspresi dikompilasi ( pohon sintaksis abstrak ). Kemudian Anda dapat mengompilasinya sekali dan mengevaluasinya berulang kali dengan nilai yang berbeda:
public static void main(String[] args) {
Map<String,Double> variables = new HashMap<>();
Expression exp = parse("x^2 - x + 2", variables);
for (double x = -20; x <= +20; x++) {
variables.put("x", x);
System.out.println(x + " => " + exp.eval());
}
}
Tipe data yang berbeda:
Alih-alih double
, Anda bisa mengubah evaluator untuk menggunakan sesuatu yang lebih kuat seperti BigDecimal
, atau kelas yang mengimplementasikan bilangan kompleks, atau bilangan rasional (pecahan). Anda bahkan dapat menggunakan Object
, memungkinkan beberapa campuran tipe data dalam ekspresi, seperti bahasa pemrograman nyata. :)
Semua kode dalam jawaban ini dirilis ke domain publik . Selamat bersenang-senang!
double x = parseTerm();
evaluasi operator kiri, setelah for (;;) {...}
evaluasi ini, operasi sukses tingkat pemesanan aktual (penambahan, pengurangan). Logika yang sama adalah dan dalam metode parseTerm. The parseFactor tidak memiliki level berikutnya, jadi hanya ada evaluasi metode / variabel atau dalam kasus paranthesis - evaluasi sub-ekspresi. The boolean eat(int charToEat)
Metode pemeriksaan kesetaraan karakter kursor saat ini dengan karakter charToEat, jika pengembalian sama benar dan pindah kursor ke karakter berikutnya, saya menggunakan nama 'menerima' untuk itu.
Untuk proyek universitas saya, saya mencari parser / evaluator yang mendukung rumus dasar dan persamaan yang lebih rumit (terutama operator yang diiterasi). Saya menemukan perpustakaan open source yang sangat bagus untuk JAVA dan .NET disebut mXparser. Saya akan memberikan beberapa contoh untuk membuat beberapa perasaan pada sintaks, untuk instruksi lebih lanjut silakan kunjungi situs web proyek (terutama bagian tutorial).
https://mathparser.org/mxparser-tutorial/
Dan beberapa contoh
1 - Furmula sederhana
Expression e = new Expression("( 2 + 3/4 + sin(pi) )/2");
double v = e.calculate()
2 - Argumen dan konstanta yang ditentukan pengguna
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 - Fungsi yang ditentukan pengguna
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 - Iterasi
Expression e = new Expression("sum( i, 1, 100, sin(i) )");
double v = e.calculate()
Ditemukan baru-baru - dalam kasus Anda ingin mencoba sintaks (dan melihat kasus penggunaan lanjutan) Anda dapat men-download Scalar Kalkulator aplikasi yang didukung oleh mXparser.
salam Hormat
HERE adalah pustaka sumber terbuka lain di GitHub bernama EvalEx.
Berbeda dengan mesin JavaScript, perpustakaan ini hanya berfokus dalam mengevaluasi ekspresi matematika saja. Selain itu, perpustakaan dapat diperluas dan mendukung penggunaan operator boolean serta tanda kurung.
Anda juga dapat mencoba juru bahasa BeanShell :
Interpreter interpreter = new Interpreter();
interpreter.eval("result = (7+21*6)/(32-27)");
System.out.println(interpreter.get("result"));
Anda dapat mengevaluasi ekspresi dengan mudah jika aplikasi Java Anda sudah mengakses database, tanpa menggunakan JAR lainnya.
Beberapa database mengharuskan Anda untuk menggunakan tabel dummy (misalnya, tabel "ganda" Oracle) dan yang lain akan memungkinkan Anda untuk mengevaluasi ekspresi tanpa "memilih" dari tabel mana pun.
Misalnya, di Sql Server atau Sqlite
select (((12.10 +12.0))/ 233.0) amount
dan di Oracle
select (((12.10 +12.0))/ 233.0) amount from dual;
Keuntungan menggunakan DB adalah Anda dapat mengevaluasi banyak ekspresi secara bersamaan. Juga sebagian besar DB akan memungkinkan Anda untuk menggunakan ekspresi yang sangat kompleks dan juga akan memiliki sejumlah fungsi tambahan yang dapat dipanggil seperlunya.
Namun kinerja dapat menderita jika banyak ekspresi tunggal perlu dievaluasi secara individual, terutama ketika DB terletak di server jaringan.
Berikut ini mengatasi masalah kinerja sampai batas tertentu, dengan menggunakan database di memori Sqlite.
Berikut ini contoh kerja lengkap di Jawa
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();
Tentu saja Anda dapat memperluas kode di atas untuk menangani banyak perhitungan secara bersamaan.
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");
Artikel ini membahas berbagai pendekatan. Berikut adalah 2 pendekatan utama yang disebutkan dalam artikel:
Mengizinkan skrip yang menyertakan referensi ke objek java.
// Create or retrieve a JexlEngine
JexlEngine jexl = new JexlEngine();
// Create an expression object
String jexlExp = "foo.innerFoo.bar()";
Expression e = jexl.createExpression( jexlExp );
// Create a context and add data
JexlContext jctx = new MapContext();
jctx.set("foo", new Foo() );
// Now evaluate the expression, getting the result
Object o = e.evaluate(jctx);
private static void jsEvalWithVariable()
{
List<String> namesList = new ArrayList<String>();
namesList.add("Jill");
namesList.add("Bob");
namesList.add("Laureen");
namesList.add("Ed");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
jsEngine.put("namesListKey", namesList);
System.out.println("Executing in script environment...");
try
{
jsEngine.eval("var x;" +
"var names = namesListKey.toArray();" +
"for(x in names) {" +
" println(names[x]);" +
"}" +
"namesListKey.add(\"Dana\");");
}
catch (ScriptException ex)
{
ex.printStackTrace();
}
}
Cara lain adalah dengan menggunakan Spring Expression Language atau SpEL yang jauh lebih banyak bersama dengan mengevaluasi ekspresi matematika karena itu mungkin sedikit berlebihan. Anda tidak harus menggunakan kerangka kerja Spring untuk menggunakan pustaka ekspresi ini karena itu berdiri sendiri. Menyalin contoh dari dokumentasi 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
Baca contoh SpEL lebih ringkas di sini dan dokumen selengkapnya di sini
jika kita akan mengimplementasikannya maka kita dapat menggunakan algoritma di bawah ini: -
Meskipun masih ada token yang harus dibaca,
1.1 Dapatkan token berikutnya. 1.2 Jika tokennya adalah:
1.2.1 Nomor: dorong ke tumpukan nilai.
1.2.2 Variabel: dapatkan nilainya, dan dorong ke tumpukan nilai.
1.2.3 Tanda kurung kiri: dorong ke tumpukan operator.
1.2.4 Tanda kurung yang tepat:
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 Seorang operator (sebut saja iniOp):
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.
Meskipun tumpukan operator tidak kosong, 1 Angkat operator dari tumpukan operator. 2 Pop nilai stack dua kali, dapatkan dua operan. 3 Terapkan operator ke operan, dalam urutan yang benar. 4 Dorong hasilnya ke tumpukan nilai.
Pada titik ini tumpukan operator harus kosong, dan tumpukan nilai harus hanya memiliki satu nilai di dalamnya, yang merupakan hasil akhir.
Ini adalah alternatif lain yang menarik https://github.com/Shy-Ta/expression-evaluator-demo
Penggunaannya sangat sederhana dan menyelesaikan pekerjaan, misalnya:
ExpressionsEvaluator evalExpr = ExpressionsFactory.create("2+3*4-6/2");
assertEquals(BigDecimal.valueOf(11), evalExpr.eval());
Saya pikir apa pun cara Anda melakukan ini akan melibatkan banyak pernyataan bersyarat. Tetapi untuk operasi tunggal seperti dalam contoh Anda, Anda dapat membatasi hingga 4 jika pernyataan dengan sesuatu seperti
String math = "1+4";
if (math.split("+").length == 2) {
//do calculation
} else if (math.split("-").length == 2) {
//do calculation
} ...
Itu menjadi jauh lebih rumit ketika Anda ingin berurusan dengan beberapa operasi seperti "4 + 5 * 6".
Jika Anda mencoba membangun kalkulator maka saya lebih baik melewati setiap bagian perhitungan secara terpisah (setiap angka atau operator) daripada sebagai string tunggal.
Sudah terlambat untuk menjawab tetapi saya menemukan situasi yang sama untuk mengevaluasi ekspresi di java, mungkin membantu seseorang
MVEL
tidak evaluasi runtime ekspresi, kita bisa menulis kode java String
untuk mendapatkannya dievaluasi dalam hal ini.
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);
Anda mungkin melihat kerangka kerja Symja :
ExprEvaluator util = new ExprEvaluator();
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30"
Perhatikan bahwa ekspresi yang pasti lebih kompleks dapat dievaluasi:
// 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
Coba kode contoh berikut menggunakan mesin Javascript JDK1.6 dengan penanganan injeksi kode.
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;
}
}
}
Ini sebenarnya melengkapi jawaban yang diberikan oleh @Boann. Ini memiliki sedikit bug yang menyebabkan "-2 ^ 2" memberikan hasil yang salah dari -4.0. Masalah untuk itu adalah titik di mana eksponensial dievaluasi dalam bukunya. Pindahkan eksponensial ke blok parseTerm (), dan Anda akan baik-baik saja. Lihat di bawah ini, yang merupakan jawaban @ Boann sedikit dimodifikasi. Modifikasi ada di komentar.
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^2 = -4
sebenarnya normal, dan bukan bug. Itu akan dikelompokkan seperti -(2^2)
. Cobalah di Desmos, misalnya. Kode Anda sebenarnya memperkenalkan beberapa bug. Yang pertama adalah bahwa ^
tidak ada lagi grup yang kanan-ke-kiri. Dengan kata lain, 2^3^2
seharusnya dikelompokkan sebagai suka 2^(3^2)
karena ^
asosiatif yang benar, tetapi modifikasi Anda membuatnya suka (2^3)^2
. Yang kedua adalah yang ^
seharusnya memiliki prioritas lebih tinggi daripada *
dan /
, tetapi modifikasi Anda memperlakukannya sama. Lihat ideone.com/iN2mMa .
package ExpressionCalculator.expressioncalculator;
import java.text.DecimalFormat;
import java.util.Scanner;
public class ExpressionCalculator {
private static String addSpaces(String exp){
//Add space padding to operands.
//https://regex101.com/r/sJ9gM7/73
exp = exp.replaceAll("(?<=[0-9()])[\\/]", " / ");
exp = exp.replaceAll("(?<=[0-9()])[\\^]", " ^ ");
exp = exp.replaceAll("(?<=[0-9()])[\\*]", " * ");
exp = exp.replaceAll("(?<=[0-9()])[+]", " + ");
exp = exp.replaceAll("(?<=[0-9()])[-]", " - ");
//Keep replacing double spaces with single spaces until your string is properly formatted
/*while(exp.indexOf(" ") != -1){
exp = exp.replace(" ", " ");
}*/
exp = exp.replaceAll(" {2,}", " ");
return exp;
}
public static Double evaluate(String expr){
DecimalFormat df = new DecimalFormat("#.####");
//Format the expression properly before performing operations
String expression = addSpaces(expr);
try {
//We will evaluate using rule BDMAS, i.e. brackets, division, power, multiplication, addition and
//subtraction will be processed in following order
int indexClose = expression.indexOf(")");
int indexOpen = -1;
if (indexClose != -1) {
String substring = expression.substring(0, indexClose);
indexOpen = substring.lastIndexOf("(");
substring = substring.substring(indexOpen + 1).trim();
if(indexOpen != -1 && indexClose != -1) {
Double result = evaluate(substring);
expression = expression.substring(0, indexOpen).trim() + " " + result + " " + expression.substring(indexClose + 1).trim();
return evaluate(expression.trim());
}
}
String operation = "";
if(expression.indexOf(" / ") != -1){
operation = "/";
}else if(expression.indexOf(" ^ ") != -1){
operation = "^";
} else if(expression.indexOf(" * ") != -1){
operation = "*";
} else if(expression.indexOf(" + ") != -1){
operation = "+";
} else if(expression.indexOf(" - ") != -1){ //Avoid negative numbers
operation = "-";
} else{
return Double.parseDouble(expression);
}
int index = expression.indexOf(operation);
if(index != -1){
indexOpen = expression.lastIndexOf(" ", index - 2);
indexOpen = (indexOpen == -1)?0:indexOpen;
indexClose = expression.indexOf(" ", index + 2);
indexClose = (indexClose == -1)?expression.length():indexClose;
if(indexOpen != -1 && indexClose != -1) {
Double lhs = Double.parseDouble(expression.substring(indexOpen, index));
Double rhs = Double.parseDouble(expression.substring(index + 2, indexClose));
Double result = null;
switch (operation){
case "/":
//Prevent divide by 0 exception.
if(rhs == 0){
return null;
}
result = lhs / rhs;
break;
case "^":
result = Math.pow(lhs, rhs);
break;
case "*":
result = lhs * rhs;
break;
case "-":
result = lhs - rhs;
break;
case "+":
result = lhs + rhs;
break;
default:
break;
}
if(indexClose == expression.length()){
expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose);
}else{
expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose + 1);
}
return Double.valueOf(df.format(evaluate(expression.trim())));
}
}
}catch(Exception exp){
exp.printStackTrace();
}
return 0.0;
}
public static void main(String args[]){
Scanner scanner = new Scanner(System.in);
System.out.print("Enter an Mathematical Expression to Evaluate: ");
String input = scanner.nextLine();
System.out.println(evaluate(input));
}
}
Bagaimana dengan sesuatu yang seperti ini:
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);
}
}
dan melakukan hal yang sama untuk setiap operator matematika lainnya sesuai ..
Dimungkinkan untuk mengubah string ekspresi apa pun dalam notasi infiks ke notasi postfix menggunakan algoritma shunting-yard Djikstra . Hasil algoritma kemudian dapat berfungsi sebagai input ke algoritma postfix dengan mengembalikan hasil dari ekspresi.
Saya menulis artikel tentang itu di sini, dengan implementasi di java
Namun pilihan lain: https://github.com/stefanhaustein/expressionparser
Saya telah menerapkan ini untuk memiliki opsi yang sederhana namun fleksibel untuk mengizinkan keduanya:
TreeBuilder yang ditautkan di atas adalah bagian dari paket demo CAS yang melakukan derivasi simbolik. Ada juga contoh interpreter BASIC dan saya sudah mulai membangun juru bahasa TypeScript yang menggunakannya.
Kelas Java yang dapat mengevaluasi ekspresi matematika:
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)))"));
}
}
Pustaka eksternal seperti RHINO atau NASHORN dapat digunakan untuk menjalankan javascript. Dan javascript dapat mengevaluasi formula sederhana tanpa mem-paring string. Tidak ada dampak kinerja juga jika kode ditulis dengan baik. Di bawah ini adalah contoh dengan 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);
}
import java.util.*;
public class check {
int ans;
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; }
//.........
}