Summor i PostScript
Jag missbrukar nu PostScript. Detta språk används ju normalt för att generera text och grafik, inte att räkna med (vid utskrift av en textfil på vårt system omvandlas texten till ett PostScript-program, som skickas till skrivaren. När programmet exekveras av datorn i skrivaren så genereras utskriften). PostScript är stackbaserat (så det liknar Javas bytekod en del), men den enda stacken jag kommer att nämna är operandstacken där man lagrar funktionsargument och resultat.
Så här kan ett PostScriptprogram för att
beräkna 5 (2
+ 3) se ut. Vi kan låta skrivaren exekvera programmet, men
enklare
är att köra PostScript-interpretatorn, gs
.
För
att slippa få upp ett textfönster och för att slippa
diverse
utskrifter ger jag några flaggor till gs
.
GS>
är gs
-prompten.
% gs -q -dNODISPLAY starta gs GS>%! GS>2 3 add 5 mul == 25 GS>5 2 3 add mul == 25 GS>quit
Några kommentarer. %!
är ett så kallat
magic
number som identifierar filen som en PostScriptfil (gör man
file
för detaljer). Varje PostScriptfil skall inledas med
%!
2 3 "pushar" termerna 2 och 3 på stacken.
Additionsoperatorn,
add
, tar, "poppar", de två översta elementen
från
stacken, adderar dessa och lägger summan överst på
stacken.
Jag pushar sedan talet 5 på stacken, multiplikationsoperatorn
mul
tar de två översta elementen från
stacken
och multiplicerar dessa och lägger produkten överst på
stacken.
== poppar det översta elementet från stacken och skriver ut
detta
(talet 25) följt av ett nyradstecken.
Nästa rad, 5 2 3 add mul ==
, visar ett annat
sätt
att utföra samma beräkning. quit
avslutar
sessionen
med interpretatorn.
Nu till vår summa. Först visar jag ett program (lägg
detta
på en fil och exekvera med gs -q -dNODISPLAY fil
)
där
jag använder "variabler", s
för summan och
k
för loopindex. %
är
kommentartecken.
%!
/s 0 def % s = 0 (ungefär) /k 0 def % k = 0 1000000 { % repetera allt inom { } 1000000 gånger /k 1 k add def % k := k + 1 (k är värdet) /s 1 k div s add def % s := s + 1 / k } repeat s == % skriv ut s quit
Lite roligare är att försöka beräkna summan utan att använda andra variabler än de som lagras på stacken. Här är en kod. Kan Du skriva en kortare?
%!
0 % 0 -> stacken, svarar mot s = 0 0 % 0 -> stacken, svarar mot k = 0 1000000 { % stackens utseende efter att raden exekverats 1 add % k+1 s dup % k k s k är nya k, (dup = duplicate) 1 % 1 k k 1 1 -> stacken exch % k 1 k s (exch = exchange) div % 1/k k s 3 -1 roll % s 1/k k (roll = cirkulärt skift) add % s+1/k k exch % k s s är nya uppdaterade s } repeat pop % s poppa k == % poppa och skriv ut s quit
Uppdelningen i rader är inte nödvändig, man kan t.ex. även skriva:
%!
0 0
1000000 {
1 add dup 1 exch div 3 -1 roll add exch}
repeat
pop ==
quit
Slutligen följer ett program där jag skriver ut summan (1/1 +
...
+ 1/10) och visar lite av styrkan med PostScript. Exekvera med gs
fil
denna gång.
%!
0 0
10 { % Summera till 10 1 add dup 1 exch div 3 -1 roll add exch} repeat pop % summan, s, ligger nu på stacken /str 20 string def % ungefär char str[20] str cvs % s konverteras till en sträng som läggs % både i str och på stacken (ungefär) /gray 0 def % sätt gråvärdet till 0, svart /incgray % öka gråvärdet (incgray är en procedur) {/gray gray 0.1 add def} def % Hitta, skala och sätt typsnitt /Times-BoldItalic findfont 26 scalefont setfont 150 150 translate % Translatera origo till (150, 150) punkter. 10 { 0 0 moveto % Flytta insättningspunkten till origo 36 rotate % Rotera 36 grader moturs % Sätt gråvärdet och öka det sedan gray setgray incgray % Skriv strängen " s = ". Insättningspunkten flyttas till slutet % av strängen. Skriv sedan textrepresentationen av vår summa. ( s = ) show str show } repeat % "Skriv ut" showpage quit
Programmet producerar följande bild: