rausfinden ob gerade oder ungerade Zahl



  • Virokams schrieb:

    Mein Cheffe sagt das manche VOrzeichenkombinationen jedoch zulässig sind ( +- -- und -+ ) obwohl wie du ja sagst man nicht weiß was der User wirklich meinte.

    mathematisch (logisch) gesehen, nein. Wie ich schon sagte, mit dem Kalkül wirst du einen Ausdruck der Form "2+-2" nicht finden. Das ist nur rein formell (siehe mathematische Logik, Aufbau der Sprache(n) der 0. bzw. 1. Stufe).

    Menschen sind aber keine Maschinen, somit arbeiten wir in einer höhren Ebene mit einer anderen Abstraktion. Wenn wir "2+-2" auf dem Papier schreiben, werden 99% der Menschen sagen, es handelt sich um "2 plus die Zahl -2". D.h. dadruch, dass wir in einer "Metasprache" den Ausdruck "2+-2" geschrieben habe, interpretieren wir den Ausdruck anders, als was er wirklich aussagt. [1]

    Ein Computer kann das aber nicht, ein Computer kann nur den Ausdruck nach festen Regeln interpretieren, nämlich jene, die durch den Kalkül vorgegeben sind. Deswegen wird der Computer (bzw. Programm) "2+-2" nicht auswerten können, weil diese Regel gar nicht existiert. Der Computer kann nicht herausfinden, was der User vielleicht gemeint haben soll. Wären wir so weit, dann würde der Computer sicher den Turing Test bestehen. Da man mit einer formalen Programmiersprache so etwas nicht realisieren kann, müssen sich letztendlich die Programmier auf die mathematische korrekte Eingaben verlassen und eben "2+-2" ablehnen. Du kannst natürlich sagen "wenn ich A+-B sehe, dann ist es so, als hätte der User A+(-B)" eingebenen, aber selbst das wäre nicht eindeutig genug. Aus diesem Grund finde ich, dass das einzige Korrekte ist, solche mehrdeutige (und mathematisch logisch gesehen ungültige) Ausdrücke von Anfang an zu verbieten.

    //edit:

    ~fricky schrieb:

    ist das nicht egal?

    siehe oben, sehr formal gesehen ist 3++3 kein Ausdruck, den man sinvoll interpretieren kann . Siehe Kapitel über Interpretation von Ausdrücken (der 1. Stufe) in der mathematischen Logik.

    //edit2
    [1] um diesen Absatz genau zu verstehen, weise ich auf
    Einführung in die mathematische Logik | ISBN: 3827416914
    hin (ich hab bei einem der Autoren meine Nebenfach Prüfung gemacht ;))



  • Zum glück Studier ich keine Mathematik oder sowas... alleine das wort Kalkül hört sich schlimmer an als Exorzismus 😉

    😃



  • Wieso kann der Computer dann:

    int a = 2;
    int b = -2;
    int c = a + b;
    ?



  • supertux schrieb:

    Virokams schrieb:

    Mein Cheffe sagt das manche VOrzeichenkombinationen jedoch zulässig sind ( +- -- und -+ ) obwohl wie du ja sagst man nicht weiß was der User wirklich meinte.

    mathematisch (logisch) gesehen, nein.

    Ich finde, das ist eindeutig, vielleicht verdenke ich mich aber auch. Je nach Operatoren-Alphabet halt, wenn es "--" als Operator gibt (wie in C/C++), ist a---b nicht eindeutig, sonst aber schon (ok, es dürfte auch keinen '-'-Post-Operator geben).

    Ein Ausdruck besteht doch aus mehreren, durch binäre Operatoren verknüpften, Elementen, welche jeweils Kernelemente (wie 'a' oder '7') inklusive eventueller Prä- und Post-Operatoren sind.
    Mit dem Operatoren-Alphabet (binär +,-; prä +,-) ist a---b eindeutig, mal von links nach rechts auseinandernehmen:
    'a' ist ein Kernelement ohne unäre Prä-Operatoren
    '-' muss der binäre Operator '-' sein, denn nach 'a' gab's noch keinen binären Operator und sonst müsste es unärer Post-Operator für 'a' sein, gibt's in unserem Alphabet nicht
    '-' Binäre Operator wurde schon gefunden, zwei hintereinander gibt's nicht, also muss das ein Prä-Operator für's nächste Kernelement sein
    '-' Dito
    'b' ist wieder Kernelement, passt, hat zwei unäre Prä-Operatoren

    Damit ergibt sich eindeutig a-(-(-b)) .

    edit: Ein Satz umformuliert



  • supertux schrieb:

    sehr formal gesehen ist 3++3 kein Ausdruck, den man sinvoll interpretieren kann . Siehe Kapitel über Interpretation von Ausdrücken (der 1. Stufe) in der mathematischen Logik.

    Von welchem Kalkül sprichst du? Betrachte z.B. folgenden Kalkül:

    0+0   0-0
    ---   ---
     0     0
    
    1+0   1-0
    ---   ---
     1     1
    
    0+1   0-1
    ---   ---
     1     1
    
    1+1   1-1
    ---   ---
     0     0
    
     +0      -0
    -----   -----
      0       0
    
     +1      -1
    -----   -----
      1       1
    
    a+b mit "a wertet zu c aus" und "b lässt sich nicht weiter auswerten"
    --------------------------------------------------------------------- (1)
             c+b
    
    a+b mit "b wertet zu d aus"
    --------------------------- (2)
             a+d
    
    a-b mit "a wertet zu c aus" und "b lässt sich nicht weiter auswerten"
    --------------------------------------------------------------------- (3)
             c-b
    
    a-b mit "b wertet zu d aus"
    --------------------------- (4)
             a-d
    

    In den Regeln stehen a, b für beliebige Teilstrings. Die Sprache soll sowas sein wie

    Term   = Term+Term | Term-Term | Zahl
    Zahl   = +Zahl | -Zahl | Ziffer
    Ziffer = "0" | "1"
    

    Der Kalkül kann Terme der Form "0+--++-+1" ohne Mehrdeutigkeiten auswerten. Zum Beispiel kann bei "0+-+1" nur die Regel (4) (in Kombination mit der Regel +1 -> 1) angewendet werden, was zu "0+-1" führt. Danach Regel (2) mithilfe von -1 -> 1, ergibt "0+1". Das kann dann direkt ausgewertet werden zu 1.

    Der Kalkül rechnet semantisch gesehen in den ganzen Zahlen modulo 2, aber es spricht nichts dagegen, das auf beliebige Zahlenbereiche auszudehnen.

    Was ich damit sagen möchte: Die Mathematik ist flexibel genug, um Terme der Gestalt "0++--+--42" auf eindeutige Art und Weise auszuwerten. Nur weil ein bestimmter Kalkül nicht in der Lage ist, solche Ausdrücke eindeutig zu einer Zahl auszuwerten, heißt das nicht, dass es keiner kann.

    edit: Übrigens kommt ein Kalkül niemals alleine. Wenn man einen Kalkül definiert, muss man immer eine Sprache angeben, auf deren Wörtern der Kalkül arbeitet.



  • Belli schrieb:

    Wieso kann der Computer dann:
    int a = 2;
    int b = -2;
    int c = a + b;

    mein c-compiler (der von vs 2005, nein nicht der GCC) kann sogar:

    int a = 3, b = 1;
      int c = a + - + + + - b;
    

    dabei kommt 4 raus, aber was das soll, weiss ich auch nicht.
    🙂



  • Virokams schrieb:

    Zum glück Studier ich keine Mathematik oder sowas... alleine das wort Kalkül hört sich schlimmer an als Exorzismus 😉

    schade eigentlich, was zumindest Logik anbetrifft. Da lernst du wichtige Konzepte, die man als Programmierer gut gebrauchen könnte. Du lernst vor allem den Unterschied zwischen Syntax und Semantik, Ausdrucksstärke von Ausdrücken, usw.

    @Christoph:

    Der Kalkül rechnet semantisch gesehen in den ganzen Zahlen modulo 2

    ja, oder ob das für alle Modelle gültig ist? Man kann sich bestimmt ein Modell bauen, wo das nicht mehr zutrifft, aber das steht hier nicht zur Debatte 😉

    Bab mir beim Logik Buch geschnappt und bemerkt, dass ich von einer "falschen" Symbolmenge ausgegangen bin, wo + und · nur Funktionsymbole sind (und nicht auf 2 Arten interpretiert werden können), also Termkalkül für S={+,·,0,1}

    --- x bel. Variable
     x
    
    --- , falls c \in S Konstante
     c
    
    t1,...,tn
    ---------,   falls f \in S, f n-Stellig
    ft1,...,ftn
    

    und damit kannst du ein Ausdruck der Form 0++1 nicht erzeugen (wenn man 0+1 für +01 schreibt)

    Was ich damit sagen möchte: Die Mathematik ist flexibel genug, um Terme der Gestalt "0++--+--42" auf eindeutige Art und Weise auszuwerten. Nur weil ein bestimmter Kalkül nicht in der Lage ist, solche Ausdrücke eindeutig zu einer Zahl auszuwerten, heißt das nicht, dass es keiner kann.

    das muss ich zustimmen und einsehen. Aber wie würdest denn "3++3" parsen? ist der erste + die 2. stellige Additionsfunktion oder Vorzeichen, und wie sieht es für den dritten Plus? Die meisten algebraic Programme wie Maple/scilab/usw werden da 100% streiken und sagen "nee, verstehe den Term nicht" (zumindest in scilab ausprobiert) also geht man schon von Regeln aus, wo +/- keine Doppeldeutigkeit haben. Mir ist eigentlich egal, wofür sich der OP entscheidet, ich würde an der Stelle einen Syntax Fehler ausgeben.



  • supertux schrieb:

    Der Kalkül rechnet semantisch gesehen in den ganzen Zahlen modulo 2

    ja, oder ob das für alle Modelle gültig ist? Man kann sich bestimmt ein Modell bauen, wo das nicht mehr zutrifft, aber das steht hier nicht zur Debatte 😉

    Ja, man kann Modelle definieren, die nicht mehr isomorph zu Z/2Z sind. Aber solche Modelle enthalten dann zwangsläufig Elemente, die sich *nicht* durch Terme darstellen lassen. Modelle mit nicht darstellbaren Elementen versucht man meistens zu vermeiden.

    supertux schrieb:

    Bab mir beim Logik Buch geschnappt und bemerkt, dass ich von einer "falschen" Symbolmenge ausgegangen bin, wo + und · nur Funktionsymbole sind (und nicht auf 2 Arten interpretiert werden können), also Termkalkül für S={+,·,0,1}

    --- x bel. Variable
     x
    
    --- , falls c \in S Konstante
     c
    
    t1,...,tn
    ---------,   falls f \in S, f n-Stellig
    ft1,...,ftn
    

    und damit kannst du ein Ausdruck der Form 0++1 nicht erzeugen (wenn man 0+1 für +01 schreibt)

    Moment, das sind zwei verschiedene Ansätze.
    Dein Kalkül beschreibt, welche Terme aus einer vorgegebenen Sprache syntaktisch korrekt sind.
    Mein Kalkül beschreibt wie man syntaktisch korrekte Terme auswertet.

    Was syntaktisch korrekte Terme sind, kann man aber auch ohne Kalkül beschreiben, zum Beispiel in EBNF-Notation.



  • Christoph schrieb:

    Mein Kalkül beschreibt wie man syntaktisch korrekte Terme auswertet.

    das habe ich übersehen 🙄



  • ~fricky schrieb:

    Belli schrieb:

    Wieso kann der Computer dann:
    int a = 2;
    int b = -2;
    int c = a + b;

    mein c-compiler (der von vs 2005, nein nicht der GCC) kann sogar:

    int a = 3, b = 1;
      int c = a + - + + + - b;
    

    dabei kommt 4 raus, aber was das soll, weiss ich auch nicht.
    🙂

    Ist doch nachvollziehbar; die Plusse neutralisieren sich weg, übrig bleibt 3 - (-1) = 4 :p



  • Big Brother schrieb:

    ~fricky schrieb:

    Belli schrieb:

    Wieso kann der Computer dann:
    int a = 2;
    int b = -2;
    int c = a + b;

    mein c-compiler (der von vs 2005, nein nicht der GCC) kann sogar:

    int a = 3, b = 1;
      int c = a + - + + + - b;
    

    dabei kommt 4 raus, aber was das soll, weiss ich auch nicht.
    🙂

    Ist doch nachvollziehbar; die Plusse neutralisieren sich weg, übrig bleibt 3 - (-1) = 4 :p

    genauso könntest du sagen, dass jeweils ein + und ein - sich aufheben. übrig bleibt dann 3 + (+1). irgendwie ist doch beides blöd.
    🙂



  • ~fricky schrieb:

    Big Brother schrieb:

    ~fricky schrieb:

    Belli schrieb:

    Wieso kann der Computer dann:
    int a = 2;
    int b = -2;
    int c = a + b;

    mein c-compiler (der von vs 2005, nein nicht der GCC) kann sogar:

    int a = 3, b = 1;
      int c = a + - + + + - b;
    

    dabei kommt 4 raus, aber was das soll, weiss ich auch nicht.
    🙂

    Ist doch nachvollziehbar; die Plusse neutralisieren sich weg, übrig bleibt 3 - (-1) = 4 :p

    genauso könntest du sagen, dass jeweils ein + und ein - sich aufheben. übrig bleibt dann 3 + (+1). irgendwie ist doch beides blöd.
    🙂

    Bei den handelsüblichen Rechenregeln, zieht doch das Plus auch den kürzeren:
    3+ -1 = 2
    Aber egaaaal 🙂



  • Der erste ist ein Operand, alle weiteren sind Vorzeichen.



  • Ich versteh immer noch nur Bahnhof 😃

    nunja ich setze jetzt einfach um das bei ungeraden - ein - "entsteht" und bei gerader anzahl - ein +

    ist glaube das einfachste für mich und reicht völlig aus für die Aufgabe die ich zu lösen habe ^^ auch wenn es für manche von euch dann Mathematisch unkorrekt ist 😛

    Dann werden die Leute mein Fertigen Rechner nicht nutzen wollen 😃 😃

    gruß



  • Virokams schrieb:

    nunja ich setze jetzt einfach um das bei ungeraden - ein - "entsteht" und bei gerader anzahl - ein +

    naja, dann bau wenigstens noch ein, dass aus einer ungeraden anzahl von '/' ein '*' wird.
    🙂



  • ~fricky schrieb:

    Virokams schrieb:

    nunja ich setze jetzt einfach um das bei ungeraden - ein - "entsteht" und bei gerader anzahl - ein +

    naja, dann bau wenigstens noch ein, dass aus einer ungeraden anzahl von '/' ein '*' wird.
    🙂

    muss das so? XD damit hab ich mich noch garnicht auseinander gesetzt



  • Virokams schrieb:

    muss das so?

    nein, natürlich nicht. das war nur ein blöder scherz.

    Virokams schrieb:

    damit hab ich mich noch garnicht auseinander gesetzt

    na, dann mach das doch mal. was soll dein programm denn mit 2/*/7 anstellen?
    🙂



  • nunja bei sowas hab ich einfach nen Fehler eingebaut XD also eine Fehlermeldung...

    bei dem +-+- dings problem soll ich aber eine Lösung geben -.- da darf ich keine Fehlermeldung ausgeben (was natürlich das einfachste wäre ... und sogar noch Math. richtig -.- )

    nunja...



  • Virokams schrieb:

    bei dem +-+- dings problem soll ich aber eine Lösung geben -.- da darf ich keine Fehlermeldung ausgeben

    eine fehlermeldung ist doch auch eine lösung (wahrscheinlich die einzig richtige bei sowas wie +--++--+--). aber du könntest es ja benutzerfreundlich gestalten, indem der cursor auf die stelle springt, mit der dein parser nicht mehr klar kommt und den user zum ausbessern auffordern. dann muss er nicht den ganzen ausdruck nochmal reinhacken.
    🙂



  • ~fricky schrieb:

    eine fehlermeldung ist doch auch eine lösung (wahrscheinlich die einzig richtige bei sowas wie +--++--+--). aber du könntest es ja benutzerfreundlich gestalten, indem der cursor auf die stelle springt, mit der dein parser nicht mehr klar kommt und den user zum ausbessern auffordern. dann muss er nicht den ganzen ausdruck nochmal reinhacken.
    🙂

    klingt gut nur glaube ich schaffe ich das von meinem Wissensstand nicht XD

    naja hier ist meine Lösung wie es jetzt inplementiert ist und sogar "funktioniert"...

    char * my_zeichenstrcpy2(char* dest, const char * source)
    {
    	int j = 0;
    	int minus = 0;
    	int i=0;
    	int einmalnur = 0;
    	int zeichen = -1;
    	int operatorenbegin = -1;
    	int nureinmal = 0;
    	int k;
    
    	for (int i=0; source[i] != '\0'; i++)
    	{
    		if (isdigit(source[i]))//source[i] != '+' || source[i] != '-')
    		{
    			dest[j] = source[i];
    			j++;
    		}
    		else if (source[i] == '+' || source[i] == '-')
    		{
    			for(int k = i; ispunct(source[k]) ; k++)
    			{
    				if (source[k] == '-')
    				{
    					minus = minus + 1;
    					zeichen = zeichen + 1;
    				}
    				i = k;
    			}
    			double unodergerade = minus % 2;
    
    			if ( unodergerade != 0 )
    				dest[j++] = '-';
    			else
    				dest[j++] = '+';
    		}
    	}
    	dest [j] = '\0';
    	return dest;
    }
    

    gruß

    Edit:

    zeichen = zeichen + 1; kann natürlich weg
    und das kommentar in Zeile 14 ebenso.


Anmelden zum Antworten