String
Değerler gibi basit matematik ifadeleri değerlendirmek için bir Java rutin yazmaya çalışıyorum :
"5+3"
"10-40"
"10*3"
Ben if-then-else deyimlerini bir sürü önlemek istiyorum. Bunu nasıl yapabilirim?
String
Değerler gibi basit matematik ifadeleri değerlendirmek için bir Java rutin yazmaya çalışıyorum :
"5+3"
"10-40"
"10*3"
Ben if-then-else deyimlerini bir sürü önlemek istiyorum. Bunu nasıl yapabilirim?
Yanıtlar:
JDK1.6 ile, yerleşik Javascript motorunu kullanabilirsiniz.
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();");
- programın şu anki dizinine (varsayılan olarak) JavaScript aracılığıyla bir dosya
eval
Bu soruyu cevaplamak için aritmetik ifadeler için bu yöntemi yazdım . Toplama, çıkarma, çarpma, bölme, üs alma ( ^
sembolü kullanarak ) ve gibi birkaç temel işlevi yapar sqrt
. (
... kullanarak gruplandırmayı destekler )
ve operatörün öncelik ve ilişkilendirilebilirlik kurallarını doğru hale getirir .
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();
}
Misal:
System.out.println(eval("((4 - 2^3 + 1) * -sqrt(3*3+4*4)) / 2"));
Çıktı: 7.5 (doğru olan)
Ayrıştırıcı özyinelemeli bir iniş ayrıştırıcısıdır , bu nedenle dahili olarak dilbilgisinde her bir operatör önceliği düzeyi için ayrı ayrıştırma yöntemleri kullanır. Kısa tuttum, bu yüzden değiştirmesi kolay, ancak burada genişletmek isteyebileceğiniz bazı fikirler var:
Değişkenler:
Ayrıştırıcının işlev adlarını okuyan bit, eval
a Map<String,Double> variables
.
Ayrı derleme ve değerlendirme:
Değişkenler için destek ekledikten sonra, aynı ifadeyi her seferinde ayrıştırmadan değiştirilen değişkenlerle milyonlarca kez değerlendirmek isteseydiniz? Mümkün. İlk olarak, önceden derlenmiş ifadeyi değerlendirmek için kullanılacak bir arabirim tanımlayın:
@FunctionalInterface
interface Expression {
double eval();
}
Şimdi double
s döndüren tüm yöntemleri değiştirin , bunun yerine bu arabirimin bir örneğini döndürürler. Java 8'in lambda sözdizimi bunun için harika çalışıyor. Değişen yöntemlerden birine örnek:
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;
}
}
}
Bu Expression
, derlenmiş ifadeyi ( soyut bir sözdizimi ağacı ) temsil eden özyinelemeli bir nesne ağacı oluşturur . Ardından bir kez derleyebilir ve farklı değerlerle tekrar tekrar değerlendirebilirsiniz:
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());
}
}
Farklı veri türleri:
Bunun yerine double
, değerlendiriciyi daha güçlü bir şey BigDecimal
veya karmaşık sayılar veya rasyonel sayılar (kesirler) uygulayan bir sınıf kullanacak şekilde değiştirebilirsiniz . Hatta Object
gerçek bir programlama dili gibi ifadelerde bazı veri türlerinin karışımına izin vererek kullanabilirsiniz . :)
Bu yanıttaki tüm kodlar kamuya açıklandı . İyi eğlenceler!
double x = parseTerm();
sol operatörü değerlendirir, bundan sonra for (;;) {...}
gerçek sipariş seviyesinin başarılı işlemlerini (toplama, çıkarma) değerlendirir. Aynı mantık parseTerm yöntemindedir. ParseFactor bir sonraki seviyeye sahip değildir, bu nedenle sadece yöntemlerin / değişkenlerin değerlendirmeleri veya parantez durumunda - alt ifadeyi değerlendirin. boolean eat(int charToEat)
Sonraki karaktere eşit dönüş doğru ve hareket imleç, adını kullanırsanız charToEat karakteri ile geçerli imleç karakterin yöntem onay eşitliği, bunun için 'kabul'.
Bunu çözmenin doğru yolu bir lexer ve bir ayrıştırıcıdır . Bunların basit sürümlerini kendiniz yazabilirsiniz veya bu sayfalarda ayrıca Java lexers ve ayrıştırıcılara bağlantılar bulunur.
Özyinelemeli bir iniş ayrıştırıcısı oluşturmak gerçekten iyi bir öğrenme alıştırmasıdır.
Üniversite projem için hem temel formülleri hem de daha karmaşık denklemleri (özellikle yinelenen operatörler) destekleyen bir ayrıştırıcı / değerlendirici arıyordum. MXparser adlı JAVA ve .NET için çok güzel bir açık kaynak kütüphane buldum. Sözdizimi hakkında bir şeyler yapmak için birkaç örnek vereceğim, daha fazla talimat için lütfen proje web sitesini (özellikle eğitim bölümü) ziyaret edin.
https://mathparser.org/mxparser-tutorial/
Ve birkaç örnek
1 - Basit furmula
Expression e = new Expression("( 2 + 3/4 + sin(pi) )/2");
double v = e.calculate()
2 - Kullanıcı tanımlı argümanlar ve sabitler
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 - Kullanıcı tanımlı işlevler
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 - İterasyon
Expression e = new Expression("sum( i, 1, 100, sin(i) )");
double v = e.calculate()
Son zamanlarda bulundu - sözdizimini denemek (ve gelişmiş kullanım durumunu görmek) durumunda mXparser tarafından desteklenen Skaler Hesap Makinesi uygulamasını indirebilirsiniz.
Saygılarımla
BURAYA , GitHub'da EvalEx adlı başka bir açık kaynak kütüphanesidir.
JavaScript motorunun aksine, bu kütüphane yalnızca matematiksel ifadeleri değerlendirmeye odaklanmıştır. Dahası, kütüphane genişletilebilir ve mantıksal işleçlerin yanı sıra mantıksal işleçlerin kullanımını destekler.
BeanShell yorumlayıcısını da deneyebilirsiniz :
Interpreter interpreter = new Interpreter();
interpreter.eval("result = (7+21*6)/(32-27)");
System.out.println(interpreter.get("result"));
Java uygulamanız başka bir JAR kullanmadan bir veritabanına zaten erişiyorsa ifadeleri kolayca değerlendirebilirsiniz.
Bazı veritabanları sahte bir tablo kullanmanızı gerektirir (ör. Oracle'ın "ikili" tablosu) ve diğerleri ise herhangi bir tablodan "seçmeden" ifadeleri değerlendirmenize olanak tanır.
Örneğin, Sql Server veya Sqlite
select (((12.10 +12.0))/ 233.0) amount
ve Oracle'da
select (((12.10 +12.0))/ 233.0) amount from dual;
Bir DB kullanmanın avantajı, aynı anda birçok ifadeyi değerlendirebilmenizdir. Ayrıca çoğu DB, oldukça karmaşık ifadeler kullanmanıza izin verir ve ayrıca gerektiğinde çağrılabilecek bir dizi ekstra işleve sahiptir.
Ancak, özellikle DB bir ağ sunucusunda bulunuyorsa, birçok tek ifadenin ayrı ayrı değerlendirilmesi gerekirse performans düşebilir.
Aşağıda, bir Sqlite bellek içi veritabanı kullanılarak performans sorunu bir dereceye kadar ele alınmaktadır.
İşte Java'da çalışan tam bir örnek
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();
Tabii ki, aynı anda birden fazla hesaplamayı işlemek için yukarıdaki kodu genişletebilirsiniz.
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");
Bu makalede çeşitli yaklaşımlar tartışılmaktadır. Makalede bahsedilen 2 temel yaklaşım şunlardır:
Java nesnelerine başvurular içeren komut dosyalarına izin verir.
// 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();
}
}
Başka bir yol da, matematiksel ifadeleri değerlendirmekle birlikte çok daha fazlasını yapan Bahar İfade Dili veya SpEL'i kullanmaktır, bu nedenle belki biraz fazla olabilir. Bu ifade kitaplığını tek başına olduğu için kullanmak için Spring çerçevesini kullanmanız gerekmez. SpEL belgelerinden örnekler kopyalanıyor:
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
Burada kısa özlü SpEL örneklerini ve tüm belgeleri burada okuyun
Eğer bunu uygulayacaksak aşağıdaki algoritmayı kullanabiliriz:
Hâlâ okunacak jetonlar olsa da,
1.1 Bir sonraki kodu alın. 1.2 Belirteci:
1.2.1 Bir sayı: değer yığınına itin.
1.2.2 Bir değişken: değerini alın ve değer yığınına itin.
1.2.3 Sol parantez: operatör yığınına itin.
1.2.4 Doğru parantez:
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 Bir operatör (buna OperaP deyin):
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.
Operatör yığını boş değilken, 1 Operatörü operatör yığınından açın. 2 İki işlenen elde ederek değer yığınını iki kez açın. 3 Operatörü işlenenlere doğru sırayla uygulayın. 4 Sonucu değer yığınına itin.
Bu noktada operatör yığını boş olmalı ve değer yığını içinde sadece bir değer olmalıdır, bu da nihai sonuçtur.
Bu başka ilginç bir alternatif https://github.com/Shy-Ta/expression-evaluator-demo
Kullanımı çok basittir ve işi yapar, örneğin:
ExpressionsEvaluator evalExpr = ExpressionsFactory.create("2+3*4-6/2");
assertEquals(BigDecimal.valueOf(11), evalExpr.eval());
Sanırım bunu her ne şekilde yaparsanız yapın, birçok koşullu ifade içerecektir. Ancak, örneklerinizdeki gibi tekli işlemler için ifadeler aşağıdaki gibi ise 4 ile sınırlayabilirsiniz.
String math = "1+4";
if (math.split("+").length == 2) {
//do calculation
} else if (math.split("-").length == 2) {
//do calculation
} ...
"4 + 5 * 6" gibi çoklu işlemlerle uğraşmak istediğinizde çok daha karmaşık bir hal alıyor.
Bir hesap makinesi oluşturmaya çalışıyorsanız, o zaman hesaplamanın her bölümünü tek bir dize yerine ayrı ayrı (her sayı veya operatör) geçirerek cerrah olurum.
Cevaplamak için çok geç ama java'daki ifadeyi değerlendirmek için aynı duruma rastladım, birisine yardımcı olabilir
MVEL
ifadelerin çalışma zamanı değerlendirmesi yaparsa, String
bunu değerlendirmek için içine bir java kodu yazabiliriz .
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);
Symja çerçevesine bir göz atabilirsiniz :
ExprEvaluator util = new ExprEvaluator();
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30"
Kesinlikle daha karmaşık ifadelerin değerlendirilebileceğini unutmayın:
// 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
Kod enjeksiyon işlemeli JDK1.6'nın Javascript motorunu kullanarak aşağıdaki örnek kodu deneyin.
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;
}
}
}
Bu aslında @Boann tarafından verilen yanıtı tamamlıyor. "-2 ^ 2" nin -4.0 hatalı sonucunu vermesine neden olan küçük bir hata vardır. Bunun sorunu, üssün kendi içinde değerlendirildiği noktadır. Üstellemeyi parseTerm () bloğuna taşımanız yeterlidir. @ Boann'ın cevabı biraz değiştirilmiş olan aşağıdakilere bir göz atın . Değişiklik yorumlarda.
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
aslında normaldir ve bir hata değildir. Gibi gruplandırılır -(2^2)
. Örneğin Desmos üzerinde deneyin. Kodunuz aslında birkaç hata içeriyor. Birincisi ^
artık sağdan sola gruplanmaması. Başka bir deyişle, 2^3^2
böyle grubuna gerekiyordu 2^(3^2)
çünkü ^
sağ ilişkisel, ama sizin modifikasyonlar bu grup gibi yapmak (2^3)^2
. İkinci olmasıdır ^
daha yüksek önceliğe sahip gerekiyordu *
ve /
ancak değişiklikler bunu aynı davranın. Bkz. İdeone.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));
}
}
Böyle bir şeye ne dersin:
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);
}
}
ve benzer şeyleri diğer matematiksel operatörler için de yapın.
Djikstra'nın manevra alanı algoritmasını kullanarak, infix notasyonundaki herhangi bir ifade dizesini bir postfix notasyonuna dönüştürmek mümkündür . Algoritmanın sonucu, ifadenin sonucunu döndürerek postfix algoritmasına girdi olarak hizmet edebilir .
Burada, Java'da bir uygulama ile ilgili bir makale yazdım
Başka bir seçenek: https://github.com/stefanhaustein/expressionparser
Ben her ikisi de izin basit ama esnek bir seçenek var bunu uyguladık:
Yukarıda bağlanan TreeBuilder , sembolik türetme yapan bir CAS demo paketinin parçasıdır . Ayrıca bir BASIC tercüman örneği var ve bunu kullanarak bir TypeScript yorumlayıcısı oluşturmaya başladım .
Matematiksel ifadeleri değerlendirebilen bir Java sınıfı:
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)))"));
}
}
Javascript çalıştırmak için RHINO veya NASHORN gibi harici kütüphane kullanılabilir. Javascript, dizeyi ayrıştırmadan basit formülü değerlendirebilir. Kod iyi yazılmışsa performans etkisi de yoktur. Aşağıda RHINO ile bir örnek -
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; }
//.........
}