Toon posts:

[JAVA] Formule evalueren *

Pagina: 1
Acties:
  • 627 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Waarschijnlijk is het antwoord eenvoudig, maar ik ben dan ook maar een beginner.

Ik zal mijn probleem proberen uit te leggen mbv een eenvoudig voorbeeld:

Ik geef volgende berekening mee als String: 17 + 38 * 2 -22.
Ik wil deze String omzetten naar een wiskundige formule.
Ik dacht de StringTokenize class te gebruiken.

Maar hoe zet ik de +,- en * tekens om naar operatoren?


String s = "17 + 38 * 2 - 22";

StringTokenizer strok = new StringTokenizer (s, " ");
int ela = new Integer(strok.nextToken());
String b= strok.nextToken();
int elc = new Integer(strok.nextToken());
String d = strok.nextToken();
int ele = new Integer(strok.nextToken());
String f = strok.nextToken();
int elg = new Integer(strok.nextToken());

System.out.println(ela + b + elc + d + ele + f + elg);

Acties:
  • 0 Henk 'm!

  • bat266
  • Registratie: Februari 2004
  • Laatst online: 12-10 09:29
hetgeen je kunt doen is kijken welke token je krijgt met een if(b == "*") bijvoorbeeld en daar de operatie van af laten hangen.

Better to remain silent and be thought a fool then to speak out and remove all doubt.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ja maar dan moet ik ze in volgorde dat ze zich aanbieden verwerken: (((17+38)*2)-22) en dat is toch nog iets anders dan hier staat: 17 + (38*2) - 22

Acties:
  • 0 Henk 'm!

  • asfaloth_arwen
  • Registratie: Februari 2005
  • Laatst online: 06:30
Zoek eens naar een eenvoudige parsing techniek bijv: niet efficient is opslaan in een queue, en als duidelijk is wat de betekenis is van de operator, queue zo ver als duidelijk leeghalen.

Specs


Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 14-10 12:42

NetForce1

(inspiratie == 0) -> true

Misschien moet je even zoeken, je bent nl niet de eerste met een probleem als dit.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

Dit gaat je denk ik niet zomaar lukken met een tokenizer alleen. Je moet namelijk ook rekening houden met operator precedence, i.e. vermenigvuldiging heeft een hogere prioriteit dan b.v. optellen, en wanneer je dus zoekt naar een generieke oplossing om met dergelijke 'formules' te werken, dan kom je toch al gauw in het domein terecht van lexers en parsers.

Je zult dan een grammatica moeten opstellen voor je 'taal', waaruit je grammatica regels naar voren komen. Daaruit komt niet alleen naar voren wat je tokens e.d. zijn (je vocabulaire), maar ook in dit geval hoe je precedence gedefineerd is. Niet echt stof om je meteen als beginner in te storten vermoed ik, en ik raad je aan om eventueel ook te kijken naar bestaande mathlexers/parsers.

Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Als je Java 6 gebruikt, kun je gebruik maken van de javax.script API.
http://java.sun.com/devel...s/J2SE/Desktop/scripting/

Dan kun je gewoon net als in JavaScript evallen...

Fat Pizza's pizza, they are big and they are cheezy


Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem


Acties:
  • 0 Henk 'm!

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 22:20
Ik denk dat er wel ergens utility libraries zijn te vinden die dit kunnen afhandelen.
Zoek eens op Math.

Als je het zelf wil doen, zul je toch een aantal functies moeten maken die de tekst recursief afhandelen. Dus iets als:
Java:
1
2
3
4
5
6
7
8
9
10
11
int calculateValue(String tekst)
{
  if( tekst.indexOf("*") > 0 )
  {
    return calculateValue(tekst.subString(0, tekst.indexOf("*") * calculateValue(tekst.subString( tekst.indexOf("*")+1);
  }
  if( tekst.indexOf("/") > )
  {
    // Do dit met de andere operatoren.
  }
}

let the past be the past.


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Title-change:
[JAVA] convert plus sign into arithmetic operator -> [JAVA] Formule evalueren

We posten hier in het Nederlands en daarbij is deze titel meteen duidelijker/beschrijvender ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • B-Man
  • Registratie: Februari 2000
  • Niet online
Als het simpele wiskundige expressies zijn kun je verschillende kanten op: ik heb er zelf twee gevolgd.

De eerste was het gebruik van BeanShell, wat vermoedelijk vergelijkbaar is met het huidige javax.script wat JKVA aanhaalt. Aangezien dat echter qua performance niet om over naar huis te schrijven was, besloot ik verder te zoeken. Zo kwam ik uit bij RPN, Reverse Polish Notation. Dit is een simpele manier om wiskundige expressies te ontleden en makkelijk te evalueren. Zoeken op 'java rpn' met google

Acties:
  • 0 Henk 'm!

  • mr_derk
  • Registratie: September 2005
  • Laatst online: 14-10 21:19
bat266 schreef op maandag 28 januari 2008 @ 13:53:
hetgeen je kunt doen is kijken welke token je krijgt met een if(b == "*") bijvoorbeeld en daar de operatie van af laten hangen.
dit gaat gaat problemen opleveren ivm java's stringpool. strings vergelijken met equals()

Acties:
  • 0 Henk 'm!

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 22:20
mr_derk schreef op maandag 28 januari 2008 @ 15:27:
[hetgeen je kunt doen is kijken welke token je krijgt met een if(b == "*") bijvoorbeeld en daar de operatie van af laten hangen.]

dit gaat gaat problemen opleveren ivm java's stringpool. strings vergelijken met equals()
Je moet ook chars vergelijken, dat gaat wel goed.
char b = 'A';
if( b == '*' ){ /* dit gaat wel goed */ }

let the past be the past.


Acties:
  • 0 Henk 'm!

  • bat266
  • Registratie: Februari 2004
  • Laatst online: 12-10 09:29
* bat266 kijkt naar tobo wie heeft die dubbele quotes daar neergezet ;)

Better to remain silent and be thought a fool then to speak out and remove all doubt.


Acties:
  • 0 Henk 'm!

  • BKJ
  • Registratie: April 2000
  • Laatst online: 18-09 14:52

BKJ

is er geen equivalent van eval uit php in java?

[ Voor 7% gewijzigd door BKJ op 28-01-2008 16:28 ]

Kamer huren


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

De scriptengine van Java heeft dit vast, maar eval is een potentiele security hazard zoals jullie misschien al weten. Nogmaals, een recursive descent parser voor een taal om deze expressies aan te kunnen is een hele goede oplossing hiervoor, sterker nog, de vraag van TS is een huiswerkopgave geweest bij compiler construction bij mij op school. Alleen zou ik een beginner niet aanraden zich hier meteen aan te wagen en toch eerst even te kijken of er al niet bestaande library's bestaan en die vind je met google -genoeg-, i.e. die gebaseerd zijn op recursive descent parsers met LL(1).

[ Voor 4% gewijzigd door prototype op 28-01-2008 16:39 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de tips. Met de beperkte kennis (een weekje) die ik heb en jullie tips heb ik een en ander in elkaar gestoken. Zie volgende URL voor het resultaat: http://forum.java.sun.com...threadID=5258447&tstart=0

Acties:
  • 0 Henk 'm!

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 08:10

voodooless

Sound is no voodoo!

Beetje vaag allemaal... ;)

- Waarom lengtes in bytes opslaan? Wat als je formules langer dan 128 tekens hebt (dat lijkt me niet onwaarschijnlijk)?
- StringRebuilder krijgt een string mee in de constructor om er vervolgens niets mee te doen?
- Waarom zo lastig doen met een StringTokenizer? String.split() doet het zelfde 10x sneller :)
- Waarom lengte meesturen met een array waarvan je met .length de lengte ook kun topvragen?
- Verder denk ik niet dat het handig om code in het Nederlands te schrijven en het dan te dumpen op een engels forum ;)

Voor de rest vind ik het niet echt heel erg handig op deze manier (ook al werkt het misschien wel), met name omdat het nogal verwarrend is.

Wat veel mooier is, is om een recursieve functie te maken in de vorm van hoe prometheuzz dat op het sun forum liet zien, maar dan toch net anders. Wat hij laat zien is een eval functie die twee waarden en een operator evalueert. De waarden zijn in dit getal echter enkel characters. Wat je nu wil is dat zo'n waarde op zichzelf ook weer een resultaat van een eval functie kan zijn.

Als je dat hebt is het zaak om de platte formule die je hebt te parsen naar een boom. Effectief komt het erop neer dat je op de juiste plek haakjes gaat zetten

2 + 30 - 2 * 10

wordt dan:

(((2 + 30)-2)*10)

Je roept dan de hoofd eval aan, en die ratelt de hele boom af tot ie alles klaar heeft, en geeft je het resultaat. Op deze manier kun je ook makkelijk nog veel meer berekeningen toevoegen. Natuurlijk kun je dat ook allemaal tijdens het parseprocess doen. Hier staat daar een voorbeeldje van: http://www.jguru.com/faq/view.jsp?EID=480122

Als je het helemaal netjes wil doen gebruik je natuurlijk iets als JavaCC :)

[ Voor 3% gewijzigd door voodooless op 30-01-2008 21:37 ]

Do diamonds shine on the dark side of the moon :?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Een beetje onbevredigende oplossing inderdaad. Ik denk dat TS de post van SPee niet helemaal heeft begrepen. Misschien komt dat ook omdat de volgorde van operatoren daar is omgedraaid (net als met die haakjes hierboven op dit moment). In principe is die post de eenvoudige versie van dat jguru-verhaal.

Het probleem met die methode is dat dingen als haakjes, aanhalingstekens, commentaar, enzo wat lastiger te implementeren zijn. En dat je steeds de string af moet zoeken/kopiëren. De methode die voodooless denk ik bedoeld heeft daar geen last van. Met copy/paste is dat niet veel werk eigenlijk:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class PMXTest {
    private static String tokens[];
    private static int current;

    private static int handleValue() {
        if (tokens[current].equals("(")) {
            current += 1;
            int result = handlePFactor();
            current += 1; //without check tokens[current].equals(")")
            return result;
        }
        return Integer.parseInt(tokens[current++]);
        //current+=1, see above
    }

    private static int handleXFactor() {
        int result = handleValue();
        while ((current<tokens.length) && tokens[current].equals("*")) {
            current += 1;
            result *= handleValue();
        }
        return result;
    }

    private static int handleMFactor() {
        int result = handleXFactor();
        while ((current<tokens.length) && tokens[current].equals("-")) {
            current += 1;
            result -= handleXFactor();
        }
        return result;
    }

    private static int handlePFactor() {
        int result = handleMFactor();
        while ((current<tokens.length) && tokens[current].equals("+")) {
            current += 1;
            result += handleMFactor();
        }
        return result;
    }

    public static int calculateValue(String s) {
        tokens = s.split(" ");
        current = 0;
        return handlePFactor();
    }

    public static void main(String[] args) {
        String s = args[0]; //"( 2 + 30 - 2 * 10 ) * ( 2 - 1 ) #ignore +";
        System.out.println(s + "=");
        System.out.println(calculateValue(s));
    }
}

Je kan + en - natuurlijk ook op gelijke hoogte zetten, of juist tail-recursie toepassen ipv while.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

pedorus schreef op donderdag 31 januari 2008 @ 12:01:
Een beetje onbevredigende oplossing inderdaad. Ik denk dat TS de post van SPee niet helemaal heeft begrepen. Misschien komt dat ook omdat de volgorde van operatoren daar is omgedraaid (net als met die haakjes hierboven op dit moment). In principe is die post de eenvoudige versie van dat jguru-verhaal.

Het probleem met die methode is dat dingen als haakjes, aanhalingstekens, commentaar, enzo wat lastiger te implementeren zijn. En dat je steeds de string af moet zoeken/kopiëren. De methode die voodooless denk ik bedoeld heeft daar geen last van. Met copy/paste is dat niet veel werk eigenlijk:

Java:
1
[...]

Je kan + en - natuurlijk ook op gelijke hoogte zetten, of juist tail-recursie toepassen ipv while.
Ik weet niet zeker of ik het goed lees, maar het lijkt niet met negatieve getallen overweg te kunnen.

Fat Pizza's pizza, they are big and they are cheezy


Acties:
  • 0 Henk 'm!

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 08:10

voodooless

Sound is no voodoo!

JKVA schreef op donderdag 31 januari 2008 @ 13:21:
Ik weet niet zeker of ik het goed lees, maar het lijkt niet met negatieve getallen overweg te kunnen.
Jawel: (0-x)

:+

Do diamonds shine on the dark side of the moon :?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
JKVA schreef op donderdag 31 januari 2008 @ 13:21:
Ik weet niet zeker of ik het goed lees, maar het lijkt niet met negatieve getallen overweg te kunnen.
$ java PMXTest "1 + -1 * 2"
1 + -1 * 2=
-1

Of bedoel je die andere methode van SPee? Tsja, daar kun je ook wel wat op maken. In dit geval door te zoeken op " - ", maar anders bijvoorbeeld met Matcher. Wordt wel lastig, ja.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1