Dzielenie wyrażeń matematycznych

0

Piszę program w którym muszę dzielić wprowadzone wyrażenie matematyczne (jako string), chciałbym wejściowe dane dzielić za pomocą regex
zrobiłem coś takiego:

Regex rgx = new Regex(@"[0-9]+(\.[0-9]+)?");
        MatchCollection matches = rgx.Matches(input_text);
        if (matches.Count > 0)
        {
            Console.WriteLine("{0} ({1} matches):", input_text, matches.Count);
            foreach (Match match in matches)
                Console.WriteLine("   " + match.Value);
        }

Nie działa do końca tak jak chcę - chcę uzyskać taki efekt:

  • wejściowe dane – 1+2.2*39^2
  • wyjściowe dane (w postaci tablicy) – {"1" "+" "2.2" "*" "39" "^" "2"}

to co zrobiłem wyłuskuje tylko liczby czyli dla wejściowego np "0.2+3" otrzymam {"0.2" "3"}. Z góry dzięki za pomoc ;)

0

Zastosuj odwrotną notację Polską, a dane do niej parsuj w kolejności wykonywania działań.

Bez regexów się obejdzie.

0

Powiem tak program zrobiłem w 100% działa, ominąłem regex ale kod przez to jest długi - zrobiłem to "najprościej" pętlami i warunkami opartymi na kodach ASII, działa ale kod jest brzydki a regex mógłby skrócić go znacznie i sprawić ze będzie czytelniejszy ;)

0

Dobra regexy szukają czegoś w tekscie, albo zwracają jakieś grupy, chcesz zrobić coś takiego, ze regex znajdzie grupy, potem w grupach grupy i jak nie będzie więcej grup, to wykona elementy w kolejności FILO?

Grupa to kolejność wykonywania czynności, jak jest w pierwszej grupie to ten sam piorytet, im głębiej grupa w grupie tym wyższy piorytet.

Nie wiem co by napisać, jutro ci coś może napiszę, na co wpadnę.

0

Mógłbyś traktować coś takiego:

.* - dowolna ilość znaków

(Dowolna ilość znaków . dowolna ilość znaków, jako liczbę rzeczywistą lub or dowolna ilość znaków) jako element liczby.

Może jeszcze wystąpić znak przed liczbą bez znaku, np -1. +1.

No i grupowanie to musisz każde elementy liczb + znak + element liczby sprawdzić według piorytetów, najpierw mnożenie i dzielenie, po rozwinięciu tych piorytetów to piorytety dodawania i odejmowania, no i jeszcze nawiasy wcześniej musisz jakoś wcisnąć.

Trochę to skomplikowane może wyjść, bo arytmetyka trochę jest rozbudowana według swoich praw.

1

Tu jest kod w Javie, użyty do kalkulatora tutaj: https://github.com/lion137/Java-Numeric-Calculator/blob/master/Tokenizer.java. Metody na stringach są takie same jak w C#:

import java.util.Arrays;
import java.util.List;

public class Tokenize_it {
    public static List<String> tokenize_expr(String exp){
        /*Take a string expression and returns a list of tokens; ex.:
        "(A + B -1)/ 3. 5" -> [(. A, +, B, -, 1, ), /, 3.5]
        */
        exp = exp.replace(" ", "");
        exp = exp.replace("+", " + ").replace("-", " - ").replace("/", " / ");
        exp = exp.replace("*", " * ");
        exp = exp.replace("(", " ( ").replace(")", " ) ").trim();
        List<String> exp_list = Arrays.asList(exp.split("\\s+"));
        return exp_list;
    }

    public static void main(String [] args){
        System.out.println(tokenize_expr("1+2.239*2"));//-> [1, +, 2.239, *, 2]
        System.out.println(tokenize_expr("1+2.239*2 +    (1 - 23.0000004D)"));//-> [1, +, 2.239, *, 2, +, (, 1, -, 23.0000004D, )]
    }
}

Listę i arrayliste też Powinieneś mieć:). Generalnie ta funkcja, najpierw skleja całe wyrażenie (usuwając wszystkie spacje exp = exp.replace(" ", "");), potem "otacza spacjami operatory"(więc to co zostanie to musza być liczby albo symbole!), usuwa trailing space (trim()), a na koniec (Arrays.asList(exp.split("\\s+"));) tworzy listę(jako separator używając jednej lub więcej spacji) z tego stringa. Jest to w miarę krótkie i czytelne, zero ifów i tylko jeden mały regexik:) ("\\s+"), można to modyfikować w zalezności jakie Chcesz operatory itd...

0

Nie doczytałem jakie było pytanie xd

Lion wydaje się odpowiednio odpowiedział na pytanie.

0
Czarny Ogórek napisał(a):

Zastosuj odwrotną notację Polską, a dane do niej parsuj w kolejności wykonywania działań.

Bez regexów się obejdzie.

Jemu na razie chodziło o tokenizer:), ale racja, był już na ten temat wątek niedawno; parsowanie z infix do postfix i potem ewaluowanie, jest najlepsze, ponieważ, jak sobie ustalimy kolejność działań, to możemy podawać na wejściu wyrażenie w pełni znawiasowane, w ogóle bez nawiasów, lub znawiasowane częściowo - czyli to co ludzie wklepują do konsoli i oczekuja dobrego wyniku:) i go dostaną!

0

Jak by było komuś przydatne to daję kod:


        input_text = input_text.Replace(" ", "");
        input_text = input_text.Replace("+", " + ").Replace("-", " - ").Replace("/", " / ");
        input_text = input_text.Replace("*", " * ");
        input_text = input_text.Replace("(", " ( ").Replace(")", " ) ").Trim();
        String[] to_return = input_text.Split(' ');

1 użytkowników online, w tym zalogowanych: 0, gości: 1