Just nu i M3-nätverket
Gå till innehåll

rätt prioritet då man räknar


cocacolacowboys

Rekommendera Poster

cocacolacowboys

2+2*2 = 6

2+2/2 = 3

 

Hur går jag tillväga för att få fram rätt prioritering då jag räknar. Jag tänkte använda mej av en scanner eller inputdialog.

 

Tacksam för tips för att få igång själva tänket.

 

 

 

Länk till kommentar
Dela på andra webbplatser

2+(2*2) = 8

(2+2)*2 = 8

2+(2/2) = 3

(2+2)/2 = 2

 

 

/T

 

Even when we know we´ll never find the answers, we have to keep on asking questions.

 

Länk till kommentar
Dela på andra webbplatser

cocacolacowboys

Skrev lite oklart. Jag vill veta hur man tänker när man kodar - inte hur den fungerar.

 

Länk till kommentar
Dela på andra webbplatser

Du skall nog försöka hålla dig till en tråd och fråga på om det är något du inte förstår.

Java hanterar redan '+','-','*' och '/' tecken rätt själv så förstår inte riktigt vad du är ute efter.

 

//Templar

 

Länk till kommentar
Dela på andra webbplatser

cocacolacowboys

Vad jag är ute efter? Jo, om jag matar in tex 2+2*2 i en showInputDialog, så vill jag ha svaret 6, men hur kodar jag för att få fram 6 och inte 8. Så långt har jag kommit att jag kan mata in ovanstående men den struntar i att prioritera turordningen, och jag får alltså fram 8.

 

 

Länk till kommentar
Dela på andra webbplatser

Tror det bästa är att du lär dig skriva parsers/kompilatorer med något lämpligt ramverk (i C världen hade flex/bison eller lex/yacc varit det naturliga, i java-världen finns lite alternativ).

 

Hursomhelst, om du är lat och bara just vill lösa problemet att knappa in matematiska uttryck och få dem uträknade så fungerar det här på nästan allt utom Mac (där Apple valt att slänga med en AppleScript-tolk istället för en Javascript-tolk):

import javax.script.*;

public abstract class ScriptingTest {
public static void main(String[] args) {
	ScriptEngineManager mgr = new ScriptEngineManager();
	ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
	  try {
	    Object ret = jsEngine.eval("2+2*2");
	    System.err.println(ret);
	  } catch (ScriptException ex) {
	      ex.printStackTrace();
	  }    
}
}

 

Edit: i ditt fall behöver du naturligtvis inte något så komplicerat som en flex och bison men det brukar ofta vara åt det hållet uppgifterna går när de blir svårare. Det var länge sedan jag letade efter någon bra parser-generator i java så jag har inga mer konkreta tips.

[inlägget ändrat 2009-05-29 23:03:49 av fhe]

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon

fhe gav ett uttömmande svar, men jag tror han missade grundfrågan. Jag gissar att frågan handlar om hur man anger precedens i uttryck. Svaret är att man använder parenteser i de flesta språk för detta, oavsett om det handlar om matematiska eller boolska uttryck.

 

I ditt exempel förstår jag verkligen inte att du fick ut 8 istället för 6, då multiplikation (i Java som de flesta moderna språk) har precedens framför addition. Men försök att explicit tala om för kompilatorn via parenteser, dvs.:

2+(2*2)

 

En fråga kvarstår dock förstås och det är vad du i programmet gör med det inmatade uttrycket. Det låter som du själv skrivit en (eller snott någon annans undermåliga) funktion för att parsa uttrycket. Ovanstående svar gäller förstås språkens egna syntaxparsning och inget annat.

 

[inlägget ändrat 2009-05-30 08:33:06 av Anjuna Moon]

Länk till kommentar
Dela på andra webbplatser

Jag gissar att frågan handlar om hur man anger precedens i uttryck. Svaret är att man använder parenteser i de flesta språk för detta, oavsett om det handlar om matematiska eller boolska uttryck.

Jag tolkade det nog mer som om han vill kunna hantera att användaren skriver in "2+2*2" och sen evaluera det. Då måste han naturligtvis lära sig hantera precedens, med eller utan paranteser. Har han gjort ett eget försök och bara evaluerat det från vänster till höger så blir det ju naturligtvis fel.

 

Det är förresten overkill att göra sig en egen parsergenerator, det är rätt lätt att tolka om en sträng till omvänd polsk notation och sen lösa det därifrån.

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
Jag tolkade det nog mer som om han vill kunna hantera att användaren skriver in "2+2*2" och sen evaluera det.

Jag insåg det till slut när jag läste om frågan (dvs. att han matade in något i en kontroll) därav mitt tillägg i slutet av inlägget ("En fråga kvarstår...")

 

 

det är rätt lätt att tolka om en sträng till omvänd polsk notation och sen lösa det därifrån.

Polsk notation, är det samma som att skriva om till en prefix-notation? Har inte hört uttrycket tidigare. Isåfall är det ju hyfsat lätt ja, men det det kräver nog ändå att man har lite teori bakom bältet för att klara av det också. Är inte säker på att så är fallet här.

[inlägget ändrat 2009-05-30 09:12:51 av Anjuna Moon]

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
Har aldrig funderat på vad den är om den inte är omvänd men jo, då borde det bli en prefixnotation

Gick själv in på engelska wiki nu och ja, det är prefix. Det var ett tag sedan jag skrev en parser, men jag vill minnas att man förlängde ut uttrycket i ett binärt träd. Sedan parsade man trädet beroende på hur man ville konvertera uttrycket, pre-, post- eller infix.

Hursomhelst, har man inte gjort det tidigare är det kanske inte helt självklart hur man angriper problemet.

Men eftersom ingen bakgrund har getts till vad som sker efter inmatningen får personen nöja sig med inkompletta svar. Inga gratislösningar här som sagt om ingen energi läggs i frågeställningen.

 

Länk till kommentar
Dela på andra webbplatser

Hursomhelst, har man inte gjort det tidigare är det kanske inte helt självklart hur man angriper problemet.

Första steget är att bestämma sig för om det är värt jobbet, det är ju inget kul att spendera timmar på att lära ut saker som hör till högskolenivå bara för att få ett "äsch, det där är för komplicerat" tillbaka.

 

Jag har å andra sidan inte riktigt tid, dessutom har alla mina parsers i modern tid handlat om hela språk och att använda de verktygen för matematiska uttryck blir lite som att skjuta mygg med kanon.

 

Vet man vad man letar efter för nyckelord borde det finnas hur mycket exempel som helst på sånt där om man googlar. Varenda parser-lib borde ha de fyra räknesätten som exempel i sin user guide.

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
det är ju inget kul att spendera timmar på att lära ut saker som hör till högskolenivå bara för att få ett "äsch, det där är för komplicerat" tillbaka.

Oj, där har jag varit många gånger härinne. Det känns väldigt otacksamt, det håller jag med om.

 

dessutom har alla mina parsers i modern tid handlat om hela språk och att använda de verktygen för matematiska uttryck blir lite som att skjuta mygg med kanon.

 

De jag har skrivit (parser->tolk->kompilator->tolk förstås, en parser är ju i sig själv verkningslös) i yrkeslivet har hittills legat på scriptnivå, där jag skapat egna scriptspråk för användarmanipulering av de system jag byggt. Det ligger som du antyder en hel del arbete i att bygga dessa tolkar och det gör man som sagt ogärna för att lösa sådana här simpla problem.

 

Detta sagt tycker jag ändå det är väldigt kul att bygga in kompilatorfunktionalitet och skapa så enkla men smarta script som möjligt. Man får en möjlighet att kombinera alla paradigm man stött på de senaste 25 åren och använda det man själv vill och känner passar bäst för ändamålet.

 

Länk till kommentar
Dela på andra webbplatser

cocacolacowboys

Tack för alla svar - ska försöka fixa det, men här kommer iallafall den "fungerande " koden. Problemet är som sagt att den inte prioritera * och /.

 

import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
import static javax.swing.JOptionPane.*;
import java.lang.NumberFormatException;

// RIGHT INPUT: 2 + 4 / 2 * 4 WRONG INPUT: 2+4/2*4

public class Test {

   	    public static void main(String[] args) {
           String data = showInputDialog ("Your input");
   	    String [] tokens = data.split (" "); 

   	                double a = Double.parseDouble(tokens[0]);
   	                double b;
   	                double c;
   	                double d;
   	                    for (int i=2; i<tokens.length; i=i+2){
   	                        b = Double.parseDouble(tokens[i]);
   	                            if (tokens[i-1].equals("+"))
   	                                a = a + b;
   	                            else if(tokens[i-1].equals("-"))
   	                                a = a - b;

   	                            c = Double.parseDouble(tokens[i]);
   	                            if(tokens[i-1].equals("*"))
   	                            a = a * c;

   	                            d = Double.parseDouble(tokens[i]);

   	                            if(tokens[i-1].equals("/"))

   	                            a = a / d;

   	                    }

   	                    showMessageDialog (null, a);

   	                    System.exit(0);  
   	            /*System.out.println(a);
   	            System.out.println("Type = Arithmetic");
   	            System.out.println("Type = Real");*/


}}

 

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
men här kommer iallafall den "fungerande " koden

Ok, det ligger mycket mer arbete för att få till det där och precis som fhe och jag skrivit är det inget vi tänker sätta oss och skriva åt dig.

 

Börja med att söka lite. Googla på ex. "infix binary tree mathematical" eller "parse mathematical expression"

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon

Jag kommer att fundera på en gammal diskussion jag hade på mitt förra jobb. Vi diskuterade kring varför många scriptspråk men i princip inga kompilerade språk har eval-kommandon, dvs. funktioner som exekverar sin egen kod. Det första vi kom fram till var att uttrycket som skall exekveras ligger i en sträng och av kompilatorn därmed skulle behandlas som en sådan. Då gick vi över till att kompilatorn förstås kunde hantera strängargumentet till eval-funktionen separat och kompilera även denna. Detta fungerar ju utan problem när strängen är konstant, men det ohållbara för en kompilator faller då in när man vill göra uttrycket dynamiskt (vilket är det vanligast fallet när man använder eval).

 

Till viss del har Reflections löst liknande problem i såväl Java som i .Net. En mycket trevlig och användbar teknik för kod att referera till sig själv vilket har väldigt många applikationsområden.

 

Jag har inte tänkt igenom följande överhuvudtaget, men rent spontant (i bakfyllan =) tänker jag mig att skapa en anonym metod i run-time, där metod-kroppen byggs upp med det inmatade uttrycket och sedan invoke:a denna metod. Jag vet dock inte hur väl utbyggt Java:s reflektionsmöjligheter är i förhållande till .Net,

 

Länk till kommentar
Dela på andra webbplatser

cocacolacowboys

Att få sökord som "infix binary tree mathematical" eller "parse mathematical expression" är till stor hjälp. Själv har jag kört med mitt hemsnickrade "priority of operators"

 

Länk till kommentar
Dela på andra webbplatser

Anjuna Moon
Att få sökord som "infix binary tree mathematical" eller "parse mathematical expression" är till stor hjälp. "

Att söka på Google kräver som sagt ofta en hel del "programmering" av sökord för att hamna rätt, framförallt i snäva programmeringsproblem. Hoppas du fått lite hjälp på vägen, trots vårt lite side-topic-svamlande =)

 

Själv har jag kört med mitt hemsnickrade "priority of operators"

I dessa sammanhang används ordet "precedence" i de flesta fall, hellre än "priority". Det finns en viss skillnad i orden när man pratar tekniskt. Prioritet/priority kan i sig antyda att punkter medan lägre prioritet inte nödvändigtvis behöver utföras, med precedence inte säger något om detta utan bara i vilken ordning saker skall utföras, från topp till botten.

 

 

 

[inlägget ändrat 2009-05-30 11:57:32 av Anjuna Moon]

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...