#!/usr/bin/gawk -f BEGIN { version = "gcalc V.06"; savefile = ENVIRON["HOME"] "/.gcalcsave"; system("touch " savefile); stackmin = 1; stackmax = 20; stackvis = 10; # Outputformat einstellen: CONVFMT = "%.10g"; errline = ""; PI = 3.14159265358979324; PI2 = 2 * PI; # Berechungstabellen aufbauen: # Arcus-Sinustabelle mit vorerst hinreichender Genauigkeit: for(i=0; i<=9000; i++) { sinus[i] = sin((i/100) * PI2 / 360); } # Wiederherstellen des letzten Zustandes; while (getline < savefile) { key = substr($0,1,5); num = substr($0,7,2) + 0; inhalt = substr($0,12); if (key == "STACK") { stack[num] = inhalt + 0; } else if (key == "MEM ") { mem[num] = inhalt + 0; } else if (key == "LABEL") { label[num] = inhalt; } } printStack(); } function rspace(dez,len, stmp) { if (dez != 0) { stmp = dez + ""; } else { stmp = " "; } while (length(stmp) < len) { stmp = stmp " "; } return stmp; } function accunum(num, erg) { if (num < 10) { erg = "a" num " "; } else { erg = "a" num; } return erg; } function memnum(num, erg) { if (num < 10) { erg = "m" num " "; } # m9 = else { erg = "m" num ; } # m10= ... return erg; } function printStack( i) { system("clear"); print " -- " version ": GAWK - Stack - Rechner (1999 by Tjabo Kloppenburg) --" print " (Hilfe: \"?\", \"h\", \"hilfe\", \"help\")"; print " "; for (i=stackvis; i>= stackmin; i--) { printf(" %s : %s %s = %s %s\n",accunum(i),rspace(stack[i],15),memnum(i),rspace(mem[i],15),label[i]); } printf("%s\nEingabe> ",errline); errline = ""; } function push(ele, i) { for (i=stackmax; i>= 2; i--) { stack[i] = stack[i-1]; } stack[stackmin] = ele; } function pop(ele, i,merk) { merk = stack[stackmin]; stack[stackmax] = 0; for (i=1; i< stackmax; i++) { stack[i] = stack[i+1] + ""; } return merk; } function help() { system("clear"); print " -- " version ": GAWK - Stack - Rechner (1999 by Tjabo Kloppenburg) --"; print " "; print " Erlaubte Eingaben sind:"; print " "; print " -397.403 : Dezimal- und Ganzzahlen mit/ohne Vorzeichen"; print " + - / * ^ ° : plus,minus,durch,mal, x hoch y, y-te Wurzel von x"; print " w,Q : Quadratwurzel, Quadrat"; print " i : inverse (1/x)"; print " sin,cos,tan : Trigenometrische Funktionen (DEG)"; print " pi,e,g : 3.141592653..., 2.718281828, 9.805"; print " int, frac : Nach/Vor-Kommateil abschneiden"; print " s,d,c,ca : swap,drop,clear,clear all"; print " x,q,quit : Beenden, alle Register werden gesichert"; print " s1..s10 : speichern von Stack[1] nach m1,m2..m10"; print " m1..m10 : Auslesen von m1..m10"; print " l1..l10 \"Text\" : m1..m10 mit einem Bezeichner versehen"; print " "; print " Die Eingabe einer Zahl zusammen mit einem Operator klappt nicht."; print " "; printf(" WEITER:"); } function PusheWert(wert) { push(wert); printStack(); } function abs(arg) { if (arg > 0) { return arg; } else { return -arg; } } /^s(1|2|3|4|5|6|7|8|9|10)$/ { # store in mem[1] m = substr($0,2,2) + 0; a = pop(); mem[m] = a; PusheWert(a); next; } /^m(1|2|3|4|5|6|7|8|9|10)$/ { # auslesen von mem m = substr($0,2,2) + 0; PusheWert(mem[m]); next; } /^l(1|2|3|4|5|6|7|8|9|10)/ { # Label fuer mem-Zelle setzen m = substr($0,2,2) + 0; if ( m < 10) { label[m] = substr($0,4); } else { label[m] = substr($0,5); } printStack(); next; } /^a(1|2|3|4|5|6|7|8|9|10)$/ { # Akku a erneut pushen a = substr($0,2,2) + 0; PusheWert(stack[a]); next; } /^[\-]*[0-9]+\.*[0-9]*$/ { PusheWert($0); next; } # Operationen: /^\+$/ { b = pop()+0; a = pop()+0; PusheWert(a+b); next; } /^\-$/ { a = pop() + 0; b = pop() + 0; c = b - a; PusheWert(c); next; } /^\*$/ { b = pop() + 0; a = pop() + 0; PusheWert(a*b); next; } /^\/$/ { b = pop() + 0; a = pop() + 0; if (b != 0) { push(a/b); } else { errline = "Fehler: 1/0 ist nicht definiert. "; push(a); push(b); } printStack(); next; } /^(ex|x|q|qu)/ { # Beenden exit; } /^s$/ { # swap b = pop() + 0; a = pop() + 0; push(b); push(a); printStack(); next; } /^d$/ { # drop pop(); printStack(); next; } # -------INT und FRAC------------------------------------- /^int$/ { # INT a = pop() + 0; PusheWert(int(a)); next; } /^frac$/ { # INT a = pop() + 0; PusheWert(a - int(a)); next; } # ------trigenometrische Funktionen ----------------------- /^sin$/ { # sin winkel = pop() + 0; rwinkel = winkel * PI2 / 360; # push(winkel); # push(rwinkel); # push(0); PusheWert( sin(rwinkel) ); next; } /^asin$/ { # arcsin # ich betrachte nur den ersten steigenden Zweig der Sinuskurve. # der Rest ergibt sich aus der Symmetrie! :-) # ich ermittle den rad-Winkel, wenn gefunden, wandele ich... # den am ende nach deg um. soll = pop(0) + 0; if (soll < 0) { soll = abs(soll); minus = (1==1); } else { minus = (1==2); } diffmin = 1000; i = 0; while ( (abs(sinus[i] - soll) < diffmin ) && (i <= 9000) ) { diffmin = abs(sinus[i] - soll); i += 1; } degwinkel = (i-1) / 100; if (minus) { degwinkel += 180; nr2 = 270 + (270 - degwinkel); } else { nr2 = 90 + (90 - degwinkel); } errline = "Zweite Lösung: " nr2 "°" PusheWert(degwinkel); next; } /^cos$/ { # cos a = pop() + 0; PusheWert( cos(PI2 * a / 360) ); next; } /^tan$/ { # tan winkel = pop() + 0; rwinkel = PI2 * winkel / 360; if (cos(rwinkel) != 0) { push( sin(rwinkel) / cos(rwinkel) ); } else { errline = "Fehler: Tangens ist für x = " a " nicht definiert."; push(a); } printStack(); next; } # ----------------------------------------------- /^i$/ { # inverse a = pop() + 0; if (a != 0) { push(1/a); } else { errline = "Fehler: 1/0 ist nicht definiert."; push(a); } printStack(); next; } # ----------------------------------------------- # x hoch y: /^\^$/ { # hoch exponent = pop() + 0; basis = pop() + 0; if (log(basis) == 0) { errline = "Fehler: e-log(" basis ") ist nicht definiert."; push(basis); push(exponent); } else { push( exp( exponent * log(basis)) ); } printStack(); next; } # y-te Wurzel von x: /^\°$/ { # y-te Wurzel aus x: # = x ^ (1/y) exponent = pop() + 0; basis = pop() + 0; if ((log(basis) == 0) || (exponent == 0) ) { errline = "Fehler: e-log(" basis ") nicht definiert oder exponent = 0."; push(basis); push(exponent); } else { exponent = 1 / exponent; push( exp( exponent * log(basis)) ); } printStack(); next; } # ----------------------------------------------- /^c$/ { # clear; for(i=1; i<= stackmax; i++) { push(); } printStack(); next; } /^ca$/ { # clear all for(i=1; i<= stackmax; i++) { push(); mem[i] = 0; label[i] = ""; } printStack(); next; } /^Q$/ { # Quadrat a = pop() + 0; PusheWert( a * a ); next; } /^w$/ { # Wurzel b = pop() + 0; if (b < 0) { errline = "Fehler: Wurzeln aus negativen Zahlen werden nicht unterstützt."; push(b); } else { push(sqrt(b)); } printStack(); next; } # ---- konstanten: -------------------- /^pi$/ { # PI PusheWert(3.14159265358979323846264); next; } /^e$/ { # e PusheWert(2.718281828); next; } /^g$/ { # PI PusheWert(9.805); next; } # ---- end of konstanten: -------------------- /^(?|h)/ { printStack(); help(); next; } # else: { if (length($0) == 0) { a = pop() + 0; if (a == 0) a = ""; push(a); push(a); } printStack(); } END { # Neu in 0.3: Speichern der Registerwerte nach home/.calc printf("Savefile des GAWK-Stack-Rechners von T.Kloppenburg.\n") > savefile; for(i=1; i<= 20; i++) { printf("STACK %2d = %s\n",i,stack[i]) >>savefile; if (i <= 10) { printf("MEM %2d = %s\n",i,mem[i]) >>savefile; printf("LABEL %2d = %s\n",i,label[i]) >>savefile; } } print "Savefile erstellt."; }