home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1988 / 12 / colleg / formel.mod next >
Encoding:
Text File  |  1988-09-20  |  9.9 KB  |  375 lines

  1. (*****************************************************************************
  2.  *                           FORMEL.MOD                                      *
  3.  *                        M2Amiga-Compiler                                   *
  4.  * Kern eines Formelinterpreters ohne jegliche Eingabesicherheit, der leicht *
  5.  * fuer eine echte Anwendung ausgebaut werden kann. Saemtliche Zahlen sind   *
  6.  * als REALs einzugeben, z.B. "5.0".                                         *
  7.  *                                                                           *
  8.  *     (C) 1988 TOOLBOX 12'88  & Edgar Meyzis "Der Formelinterpreter"        *
  9.  *****************************************************************************)
  10.  
  11.  
  12. MODULE RechenBaum;
  13. FROM MathLib0 IMPORT 
  14.         cos, exp, ln, sin; (*darauf beschraenkt da fuer Prinzip hinreichend *)
  15. FROM RealConversions IMPORT
  16.         StrToReal;         (* wandelt STRING in REAL *)
  17. FROM RealInOut IMPORT
  18.         done, ReadReal, WriteReal;
  19. FROM Strings IMPORT
  20.         Compare, Delete, Length;
  21. FROM Storage IMPORT (* Runtime gibt Speicherplatz bei Programmende frei*)
  22.         ALLOCATE;
  23. FROM SYSTEM IMPORT
  24.         ADR, TSIZE;
  25. FROM Terminal IMPORT
  26.         ReadLn, Write, WriteLn, WriteString;
  27.         
  28.  
  29. TYPE  STRING         = ARRAY[0..40] OF CHAR; (* begrenzt Formellaenge *)
  30.       MathFunktionen = (SIN, LN, COS); (* hier erweitern; dazu auch FunktTab
  31.                                           initialisieren und Ergebnis ausbauen
  32.                                        *)
  33.       Zeiger         = POINTER TO Knoten;
  34.       Knoten         = RECORD  (* kennen wir doch von Bild 8 !? *)
  35.                           Wert   : REAL;
  36.                           XVar   : BOOLEAN;
  37.                           Operat : CHAR;
  38.                           Links,
  39.                           Rechts : Zeiger
  40.                        END;
  41. VAR   Formel   : STRING;
  42.       Wurzel   : Zeiger;
  43.       CH       : CHAR; (* waere auch ohne gegangen *)
  44.       (* Folgende Tabellen wachsen mit Zunahme von "MathFunktionen mit *)
  45.       FunktTab : ARRAY MathFunktionen OF ARRAY[0..3] OF CHAR;
  46.       OprtrTab : ARRAY MathFunktionen OF CHAR;
  47.       
  48.  
  49.  
  50.  
  51. MODULE Initialisieren;
  52.  
  53. IMPORT FunktTab, OprtrTab, MathFunktionen, Write, WriteLn, WriteString;
  54.  
  55. VAR Index : MathFunktionen;
  56.  
  57. (* laeuft nach dem Laden des Programms ohne Aufruf automatisch ab. That`s
  58.    Modula. *) 
  59. BEGIN
  60.    Write(14C); (* DelScr*) WriteLn; WriteLn; WriteString
  61.    ("RECHENBAUM errichtet aus dem String Y = F(X) einen binären");
  62.    WriteLn; WriteString        
  63.    ("Baum, um darin Funktionswerte schnell zu berechnen.");
  64.    WriteLn; WriteLn; WriteLn;
  65.    FunktTab[SIN] := "SIN"; OprtrTab[SIN] := "S";
  66.    FunktTab[LN]  := "LN";  OprtrTab[LN]  := "N";
  67.    FunktTab[COS] := "COS"; OprtrTab[COS] := "C"; (*hier erweitern*)
  68.    WriteString("Programmierte Funktionen: SIN, COS, LN, ^, *, /, +, -");
  69.    WriteLn; WriteLn;
  70. END Initialisieren;
  71.  
  72.  
  73.  
  74.  
  75. PROCEDURE Abbrechen;
  76. BEGIN
  77.    WriteString("Wegen vermutlich fehlerhafter Eingabe abgebrochen!");
  78.    WriteLn; HALT; (* brutal aber bewusst allgemein gehalten! *)
  79. END Abbrechen;
  80.  
  81.  
  82. PROCEDURE FormelEinlesen;
  83. VAR Laenge : INTEGER;
  84.  
  85. PROCEDURE FormelAufbereiten(VAR String : STRING);
  86.  
  87. (* Leerzeichen beseitigen und in Grossbuchstaben wandeln, um "FormelLesen"
  88.    zu vereinfachen.
  89. *)
  90. VAR Pos : INTEGER;
  91. BEGIN
  92.    Pos := 0;
  93.    LOOP
  94.       IF String[Pos] = 0C THEN EXIT END;
  95.       String[Pos] := CAP(String[Pos]);
  96.       IF String[Pos] = " " THEN
  97.          Delete(String, Pos, 1);
  98.       ELSE
  99.          INC(Pos)
  100.       END;
  101.    END;
  102. END FormelAufbereiten;
  103.  
  104. BEGIN (*FormelEinlesen ohne jegliche Eingabesicherheit*)
  105.    WriteString("Y(X) = "); ReadLn(Formel, Laenge);
  106.    FormelAufbereiten(Formel);
  107. END FormelEinlesen;
  108.  
  109.  
  110. PROCEDURE BaumErrichten;
  111.  
  112. VAR Position     : INTEGER; (* innerhalb FormelString*)
  113.     FormelEnde   : BOOLEAN;
  114.     
  115. PROCEDURE FormelLesen;
  116. BEGIN
  117.    INC(Position);
  118.    IF Formel[Position] # 0C THEN
  119.       CH :=  Formel[Position];
  120.    ELSE
  121.       FormelEnde := TRUE;
  122.    END;
  123. END FormelLesen;
  124.  
  125. PROCEDURE NEW (VAR Element : Zeiger);
  126. (* M2Amiga unterstⁿtzt nicht NEW *)
  127. BEGIN
  128.    ALLOCATE(Element, TSIZE(Knoten));
  129. END NEW;
  130.  
  131. PROCEDURE KnotenAnfuegen() : Zeiger;
  132. VAR PZeig : Zeiger;
  133. BEGIN
  134.    NEW(PZeig);
  135.    WITH PZeig^ DO
  136.       Links := NIL; Rechts := NIL;
  137.       XVar  := FALSE;
  138.    END;
  139.    RETURN PZeig;
  140. END KnotenAnfuegen;
  141.  
  142. PROCEDURE NeuerKnoten (PZeig : Zeiger; Aktion : CHAR;
  143.                        Lesen : BOOLEAN)               : Zeiger;
  144. VAR QZeig : Zeiger;
  145. BEGIN
  146.    NEW(QZeig);
  147.    WITH QZeig^ DO
  148.       Links := PZeig; Operat := Aktion; XVar := FALSE;
  149.    END;
  150.    IF Lesen THEN 
  151.       FormelLesen 
  152.    END;
  153.    RETURN QZeig;
  154. END NeuerKnoten;
  155.  
  156. PROCEDURE Term() : Zeiger;
  157. VAR PZeig, QZeig : Zeiger;
  158.  
  159. PROCEDURE Produkt() : Zeiger;
  160. VAR PZeig, QZeig : Zeiger;
  161.  
  162.  
  163. PROCEDURE Exponent() : Zeiger;
  164. VAR PZeig, QZeig : Zeiger;
  165.  
  166.  
  167. PROCEDURE VorZeichen() : Zeiger;
  168. VAR PZeig, QZeig : Zeiger;
  169.  
  170.  
  171. PROCEDURE Faktor() : Zeiger;
  172. VAR PZeig, QZeig : Zeiger;
  173.     Anfang       : CARDINAL;
  174.     Gefunden     : BOOLEAN;
  175.     TeilForm     : STRING;
  176.     
  177. PROCEDURE ZiffernUmwandeln;
  178. VAR Fehler : BOOLEAN;
  179.     Index  : CARDINAL;
  180.     
  181. BEGIN
  182.    PZeig := KnotenAnfuegen();
  183.    Index := 0;
  184.    IF (CH >= "0") AND (CH <= "9") THEN
  185.       LOOP
  186.          CASE Formel[Position] OF
  187.             "0".."9",
  188.             "E", "."  : TeilForm[Index] := Formel[Position]; 
  189.           | "+", "-"  : IF TeilForm[Index - 1] = "E" THEN
  190.                            TeilForm[Index] := Formel[Position]
  191.                         ELSE
  192.                            EXIT
  193.                         END;
  194.          ELSE
  195.             EXIT
  196.          END;
  197.          INC(Index); INC(Position);
  198.       END;
  199.       TeilForm[Index] := 0C;
  200.       StrToReal(TeilForm, PZeig^.Wert, Fehler);
  201.       IF Fehler THEN
  202.          Abbrechen
  203.       END;
  204.       DEC(Position);
  205.    ELSE (* also X *)
  206.       PZeig^.XVar := TRUE;
  207.    END;
  208.    FormelLesen;
  209. END ZiffernUmwandeln;
  210.  
  211. PROCEDURE FunktionenAuswerten;
  212. VAR Index   : MathFunktionen;
  213.     Laenge  : CARDINAL;
  214. BEGIN
  215.    Gefunden := FALSE;
  216.    FOR Index := SIN TO MAX(MathFunktionen) DO (*auf Erweiterung eingestellt*)
  217.       IF NOT Gefunden THEN
  218.          Laenge := Length(FunktTab[Index]);
  219.          IF Compare(Formel, Position, Laenge, FunktTab[Index], TRUE) = 0 THEN
  220.             Gefunden := TRUE;
  221.             INC(Position, (Laenge - 1));
  222.             PZeig := KnotenAnfuegen();
  223.             QZeig := NeuerKnoten(PZeig, OprtrTab[Index], TRUE);
  224.             QZeig^.Rechts := Faktor();
  225.             PZeig := QZeig;
  226.          END;
  227.       END;
  228.    END;
  229.    IF NOT Gefunden AND FormelEnde THEN
  230.       Abbrechen
  231.    END;
  232. END FunktionenAuswerten;
  233.  
  234. BEGIN (*Faktor*)  
  235.    IF ((CH >= "0") AND (CH <= "9")) OR (CH = "X") THEN
  236.       ZiffernUmwandeln
  237.    ELSIF CH = "(" THEN
  238.       FormelLesen;
  239.       PZeig := Term();
  240.       IF CH # ")" THEN 
  241.          Abbrechen
  242.       END;
  243.       FormelLesen;
  244.    ELSE
  245.       FunktionenAuswerten
  246.    END;
  247.    RETURN PZeig;
  248. END Faktor;
  249.  
  250. BEGIN (*VorZeichen*)
  251.    (* negatives Vorzeichen wird in der Form (-1 * Ausdruck) berücksichtigt.*)
  252.    IF CH = "-" THEN
  253.       FormelLesen;
  254.       PZeig := KnotenAnfuegen();
  255.       PZeig^.Wert := -1.0;
  256.       QZeig := NeuerKnoten(PZeig, "*", FALSE);
  257.       QZeig^.Rechts := Faktor();
  258.       PZeig := QZeig;
  259.    ELSE
  260.       PZeig := Faktor()
  261.    END;
  262.    RETURN PZeig;
  263. END VorZeichen;
  264.  
  265. BEGIN (*Exponent*)
  266.    PZeig := VorZeichen();
  267.    IF CH = "^" THEN
  268.       QZeig := NeuerKnoten(PZeig, CH, TRUE);
  269.       QZeig^.Rechts := VorZeichen();
  270.       PZeig := QZeig;
  271.    END;
  272.    RETURN PZeig;
  273. END Exponent;
  274.  
  275. BEGIN (*Produkt*)
  276.    PZeig := Exponent();
  277.    IF (CH = "*") OR (CH = "/") THEN
  278.       QZeig := NeuerKnoten(PZeig, CH, TRUE);
  279.       QZeig^.Rechts := Exponent();
  280.       PZeig := QZeig;
  281.    END;
  282.    RETURN PZeig;
  283. END Produkt;
  284.  
  285. BEGIN (*Term*)
  286.    PZeig := Produkt();
  287.    IF (CH = "+") OR (CH = "-") THEN
  288.       QZeig := NeuerKnoten(PZeig, CH, TRUE);
  289.       QZeig^.Rechts := Produkt();
  290.       PZeig := QZeig;
  291.    END;
  292.    RETURN PZeig;
  293. END Term;
  294.  
  295. BEGIN            (*BaumErrichten ohne Syntax- u. Plausibilitaetspruefungen*)
  296.    Position := -1; (* FormelLesen beginnt bei Formel[0] n. Inkrementierung*)
  297.    FormelLesen;
  298.    Wurzel := Term();
  299. END BaumErrichten;
  300.  
  301.  
  302. PROCEDURE FunktionsWert(X : REAL) : REAL;
  303.  
  304. PROCEDURE BaumDurchrechnen(Wurzel, QZeig : Zeiger);
  305. VAR Oprd1, Oprd2 : REAL;
  306.     PZeig        : Zeiger;
  307.     
  308. PROCEDURE Ergebnis(Operator : CHAR) : REAL;
  309. (*ausbaubare Grundprozedur, die keine Fehler abfaengt*)
  310. BEGIN
  311.    CASE Operator OF
  312.       "*" : RETURN Oprd1 * Oprd2;
  313.     | "/" : RETURN Oprd1 / Oprd2;
  314.     | "+" : RETURN Oprd1 + Oprd2;
  315.     | "-" : RETURN Oprd1 - Oprd2;
  316.     | "^" : RETURN exp(ln(Oprd1) * Oprd2);
  317.     | "S" : RETURN sin(Oprd2);
  318.     | "C" : RETURN cos(Oprd2);
  319.     | "N" : RETURN ln(Oprd2);
  320.    END;
  321. END Ergebnis;
  322.  
  323. PROCEDURE OperandWert(PZeig : Zeiger) : REAL;
  324. BEGIN
  325.    WITH PZeig^ DO
  326.       IF XVar THEN
  327.          RETURN X
  328.       ELSE
  329.          RETURN Wert
  330.       END;
  331.    END;
  332. END OperandWert;
  333.  
  334. BEGIN (*BaumDurchrechnen*)
  335.    IF Wurzel # NIL THEN
  336.       PZeig := QZeig;
  337.       BaumDurchrechnen(Wurzel^.Links, Wurzel);
  338.       IF PZeig # Wurzel THEN
  339.          Oprd1 := OperandWert(Wurzel);
  340.          IF PZeig^.Rechts^.Links # NIL THEN
  341.             BaumDurchrechnen(PZeig^.Rechts, PZeig^.Rechts);
  342.          END;
  343.          Oprd2 := OperandWert(PZeig^.Rechts);
  344.          PZeig^.Wert := Ergebnis(PZeig^.Operat);
  345.       END;
  346.    END;
  347. END BaumDurchrechnen;
  348.  
  349. BEGIN (*FunktionsWert*)
  350.    BaumDurchrechnen(Wurzel, Wurzel);
  351.    RETURN Wurzel^.Wert;
  352. END FunktionsWert;
  353.  
  354. PROCEDURE WerteBerechnen;
  355. VAR X : REAL;
  356. BEGIN
  357.    WriteString("Programmabbruch mit <RETURN> möglich.");
  358.    WriteLn; WriteLn;
  359.    LOOP
  360.       WriteString("X = "); ReadReal(X);
  361.       IF NOT done THEN
  362.          HALT
  363.       END;
  364.       WriteString("Y = "); WriteReal(FunktionsWert(X), 8,3);
  365.       WriteLn; WriteLn;
  366.    END;
  367. END WerteBerechnen;
  368.  
  369.  
  370. BEGIN (*RechenBaum*)
  371.    FormelEinlesen;
  372.    BaumErrichten;
  373.    WerteBerechnen;
  374. END RechenBaum.
  375.