Tags: Artikel mit dem Tag «Mathematik» durchstöbern
Rechnen mit KDE4 usw.

Klassische Taschenrechner
Was macht man mit einem Computer? Rechnen? Meistens eMails lesen und schreiben, im Internet surfen, Artikel, Blogeinträge, Briefe und Aufsätze verfassen, Daten einpflegen, zocken... und hin und wieder sogar Programmieren.
Aber hier soll es wirklich einmal um das Rechnen gehen, also das womit man einen Großteil der Grundschulzeit verbracht hat, und die Anwendungen, die man dazu unter Linux/KDE4 verwenden kann.
bc
Natürlich kann man den Linux-Konsolen-Rechner bc verwenden:
Er kann mit beliebiger Genauigkeit rechen, unterstützt Variablen und zeigt den Rechenverlauf an. Daher kann man ihn auch aus Shell-Scripten verwenden, was ihn ziemlich universal einsetzbar und automatisierbar macht.
[Update 2009-12-13] Zum Beispiel lässt sich so das kartesische Produkt der Zeilen zweier Dateien A und B durch-multiplizieren:
while read lA;do while read lB;do echo $lA*$lB;done <B;done <A|bc >result
ALT+F2=
Der Programmstarter kann auch Rechnen! Sobald im Einfabefenster ein = steht wird der Rest als Term interpretiert und das Ergebnis angezeigt. Das ist sehr praktisch, wenn man schnell ein paar Kosten aufaddieren will oder ähnliches. Man kann auch gut Experimentieren, da das Ergebnis schon beim Tippen angezeigt wird.
Für kompliziertere Rechnungen wird das aber schnell unübersichtlich. Außerdem hat der Rechner leider einen Rundungsfehler, statt z.B. 5,5 zeigt er öfters 5,49999 an usw.
KCalc
Der Klassische Rechner auf KDE ist KCalc:
Es hat alle Funktionen, die man von einem solchen Rechner erwarten könnte: Funktionstasten für diverse wissenschaftliche und mathematische Funktionen, Umrechnung verschiedener Zahlensysteme, und ein geordnetes Verzeichnis von Konstanten aus fast allen Wissenschaftsbereichen. Man kann natürlich auch auch einige Tasten ausblenden.
KAlgebra
Etwas erweiterte Funktionen hat KAlgebra:
Neben der bc-ähnlichen Konsole mit Vorschlägen beim Tippen, sowie einem 2D und 3D Plotter (Siehe Fun with KAlgebra), beinhaltet er außerdem eine Funktionsliste mit graphischer Vorschau.
Wolfram Alpha
Jetzt verlassen wir das KDE-Gebiet in Richtung Internet. Auf der Webseite Wolfram Alpha lassen sich nahezu alle denkbaren Berechnungen durchführen, auch Integrieren und Rechen mit exotischen Daten (Eigenschaften Chemischer Elemente, Aktienkurse, Mathematische Modelle, Wetter usw.). Zu fast jeder Berechnung gibt es einen Graphen oder eine Illustration, zum Integrieren die Rechenschritte, zu Funktionen diverse Daten und einiges mehr. Siehe die sehr lange Liste von Beispielen und meine Lifestream-Einträge zum Schlagwort Wolfram.
Nebenbei bemerkt...

Natural Display (links)
Ich für meinen Teil rechne oft mit dem klassischen Taschenrechner, in meinem Fall der fx-85EF oder der fx-85MS, von denen ich einen fast immer griffbereit habe. Obwohl sie nicht die kompliziertesten Modelle sind haben sie neben dem grundlegenden Funktionsumfang auch noch schöne Stochastik-Funktionen und Rechnen mit Prozenten und Grad, der EF hat ein Natural Display (also „schöne“ Anzeige von Brücken, Wurzeln usw. ) und Wertetabellen.
Außerdem habe ich einen Rechenschieber, mit dem sich schnell und Stromlos zumindest die Berechnungen -, +, *, /, sin, ^2, ^3, cos, arc, tan, lg berechnen lassen.
Für Windows hier eine Empfehlung für SpeedCrunch.
Einer der besten Rechner ist sicherlich der Graphing Calculator von Pacific Tech. Er zeigt nicht nur alle Rechnungen so an, wie im Mathebuch, sondern rechnet mit Vektoren und Komplexen zahlen und plottet sogar Vierdimensionales. Gibts allerdings nur für Mac und Windows und kostet seinen Preis.
Fun with KAlgebra
One of the apps that was updated for KDE4 suite was the graphing calculator KAlgebra. It does not only have the nice live preview for all kinds of functions but also a neat 3D view. Of course this is where you can poke around best:
You can really produce impressive stuff and uncommon graphs, because you can use functions like ceiling() and abs():
3D-Perspektive mit einer kurzen Formel

3D-Effekt mit Javascript
Für die Gestaltung von 3D-Effekten, sind zwar duzende Hardware-beschleunigte Toolkits parat, doch im Fall von HTML-Canvas bzw. auf Webseiten generell sieht das Angebot nicht so reich aus. Das hat mich dazu bewegt, selbst einen kleinen Blick in die Mathematik hinter 3D-Projektionen/3D-Perspektive zu werfen. Meine Erkenntnisse konnte ich in einer kurzen Formel zusammenfassen.
Wer sich nicht für die Mathematik interessiert, kann natürlich flash oder eine der vielen Canvas-3D-Librarys verwenden.
Das Prinzip hinter der 3D-Projektion ist meist das einer Lochkamera. Lichtstrahlen fallen vom abzubildenden Punkt im Raum durch ein Loch und auf einen Schirm. Diese Art der Projektion war eine der ersten bekannten und mit ihrer alten Bezeichnung „camera obscura“ (lat. für dunkle Kammer, die in der der Schirm angebracht war) namensgebend für die heute auf Linsenoptik basierenden Kameras.
Die Lochkamera ist leider nicht so lichtstark wie die Linsenoptik und ihre Schärfe ändert sich nicht mit der Entfernung, sondern mit der Größe des Lochs.
Im Gegensatz zur Linsenoptik ist die Lochkamera aber durch den einfachen Strahlensatz zu berechnen. Mit dem Strahlensatz kann man ganz einfach die Koordinaten eines Punktes im Raum umrechnen in Koordinaten auf dem Schirm. Dazu genügt folgende Funktion:
F:ℝ³→ℝ², F(x,y,z)= P( x*d / z | y*d / z ) ; d: distance to screen
Dass diese Funktion klappt, zeigt dieses Beispiel. Hier eine Graphische Erläuterung:

Strahlensatz für Perspektive. Schwarz: Abzubildender Punkt/Lichtstrahl, Blau: Kamera, Grün: Kameraparameter Bildweite, Rot: Koordinate auf dem Schirm, Lila: Ursprungskoordinaten
Wegen dem Strahlensatz gilt x' / x = d / z, aufgelöst x' = d*x / z, analog für die y-Koordinate.
Etwas logischer wäre vielleicht der Schirm hinter dem Loch, vor allem da Objekte näher an die Kamera heran kommen können, doch so kann man sich den Schirm wie den Computerbildschirm vorstellen, durch den man in die Raumillusion hineinschaut.
Diese Formel erledigt die Abbildung in der Kamera. Jedoch muss der Punkt bereits in Koordinaten relativ zur Kamera gegeben sein. Da man normalerweise Punkte zunächst durch ein Weltkoordinatensystem definiert, muss man sie erst transformieren.
Bei meinem einfachen Beispiel beschränkt sich die Transformation zunächst auf eine Verschiebung entlang der z-Achse und später habe ich noch eine Rotation um die y-Achse hinzugefügt. Diese Koordinatenumrechnungen lassen sich in Transformationsmatrizen beschreiben.
Dann fehlt eigentlich nur noch die Darstellung. Im Beispiel wird der Text durch einfache CSS-Manipulationen an die richtige Position gebracht, und die Kreise werden mit dem canvas-Element gerendert.
Mit einem solchen Modell lassen sich schon einfache Drahtgitter problemlos darstellen (Demo), da eine Kante zwischen zwei Punkten im Raum auch eine Strecke zwischen zwei Punkten auf dem Schirm darstellt, und uns somit die Berechnung dieser Bildpunkte erspart. Für eine ausgefeiltere Darstellung kann man Dreiecke oder Polygone verwenden (Demo), für die ungefähr das selbe gilt, nur dass z.B. ihr Winkel zu einer Lichtquelle für die Kolorierung verwendet werden kann
Für nahezu realistische Lichteffekte bedarf es allerdings eines anderen Modells, genannt Raytracing, bei dem man den Weg rückwärts geht und bei der Kamera anfängt. Das wurde übrigens auch schon in Javascript umgesetzt, ist aber für Echtzeit-Anwendungen eher ungeeignet (vielleicht kommen bald die ersten Computerspiele mit der - in Realtime - noch neuen Technik).
MacMahonMosaik Online Game

Mac Mohan Mosaik
Da ich beim Känguru-Wettbewerb 2009 mitgemacht habe, habe ich auch das MacMahonMosaik in die Hände bekommen. Es ist ein kleines Rätsel ähnlich wie Sudoku. Weil es interessant zu Modellieren ist, habe ich das MacMahonMosaik als Online-Spiel erstellt. Hier ein paar Details zu Implementierung:
Modell
Jedes Quadrat im Spiel hat 4 Kanten, die in 3 verschiedenen Farben markiert sein können. Daher lässt sich jede Anordnung als 4-Tupel einer 3-Menge auffassen. Diese 81 Tupel wiederum können den natürlichen Zahlen von 0-80 zugeordnet werden. Somit habe ich als Objekte zunächst die 24 Quadrate (die anderen fallen weg, da sie durch Drehung erreicht werden können), die jeweils eine Zahl speichern. Sie müssen sich nun z.B. drehen können. Dazu wird die Zahl in das Tupel umgerechnet und die Einträge des Tupels um eine Stelle verschoben, wobei der letzte Eintrag der erste wird. Um zu Überprüfen, ob zwei Quadrate aneinander passen, dreht man eines der beiden zweimal und schaut dann einfach ob in der gewünschten Richtung die selben Farben stehen. Dadurch sieht die Prüffunktion im Javascript sehr kurz aus:
p.checkMatch=function(other,pos){
var mycodes=this.getColorCodes(); // Tupel aus Zahl
var o=other.clone(); // Neues Quadrat mit selber Zahl
var othercodes=o.rotate().rotate().getColorCodes(); // anderes Q. 2x drehen
return (mycodes.charAt(pos)==othercodes.charAt(pos)); //prüfen
}
Zusätzlich haben die Quadrate noch ein paar Darstellungsrelevante optionale Eigenschaften und Methoden. Ist ihnen ein <Canvas>-Element im HTML-Baum delegiert, können sie ihm die passenden Event-Handler für das interaktive Drehen und Bewegen zuweisen und eine graphische Repräsentation ihrer selbst zeichnen. Und sie speichern einige Daten für drag & drop.
Doch beim Ziehen und Ablegen kommt das zweite Objekt ins Spiel: Das Feld in dem die Quadrate abgelegt werden können. Wann immer man ein Quadrat bewegt, frag dieses Quadrat beim Gitter nach, ob es sich einrasten kann. Das Gitter gäbe dann die Pixel-Koordinaten des Einrastpunkts auf dem Bildschirm und die Koordinaten innerhalb des Gitters zurück. Wird das Quadrat dann fallen gelassen, registriert es sich im Gitter.
Das Gitter hat dazu ein zweidimensionales Feld hinterlegt, in dem es Pointer zu den abgelegten Quadraten speichern kann. Wenn jetzt ein Quadrat im Raster abgelegt wird und sich registriert hat, weist es das Raster an, sich zu revalidieren - Das Gitter ruft für jedes Quadrat und je seine vier Nachbarn die Prüffunktion auf. (Da das „Passen“ symmetrisch ist, ließe sich die Komplexität des Algorithmus vielleicht noch optimieren, doch das hätte wieder mehr Code zur Folge und bei 24 Einheiten...) Da das Gitter nur Zeiger zu den Quadraten speichert, ist bei einer Drehung eines Quadrats keine weitere Registrierung nötig. Falls also ein Quadrat angeklickt wird, rotiert es sich, aktualisiert die eigene Darstellung und gibt den Revalidierungsbefehl an das Raster.
Für die Darstellung hat das Gitter auch eine recht einfache Methode, die den Feldhintergrund rötlich färbt, sollte ein Fehler vorliegen und eine Gratulation meldet, sollten alle Quadrate an einem passenden Ort sein, also das Spiel gewonnen.
Ablaufdiagramm
Hier mal ein kleiner Flowchart. Man beginne das Lesen bei den Event-Handlern: (erstellt mit U+2500-U+257F: Box Drawing)
Quadrat
├ Zahl ◁──────┐ {Umrechnung}
├ (Tupel) ◁───┘
├ Drehen() ◀────────┐◁──┐─┐▷─────┐
├ Prüfen(Quadrat) ──◆───┊─┊──────┊──┐
├ [Darstellung] │ │ │ │ │
│ ├ Visualisieren◁─┊───┊─┘ │ │
│ └ [Handler] │ │ │ └──┐
│ ├ Klick ──────┊───┘ │ │
│ ├ Packen ────┊────────────┊──┐ │
│ ├ Bewegen ◀───┊───┐ │ │ │
│ └ Ablegen ────┊─────────┬▷─┤ │ │
└ Kopieren() ►──────┘ │ │ │ │ ▼ bool
[XY,XY] │ │ │ │
Gitter │ │ │ │ │
├ Feld[X,Y] │ │ │ │ │
├ KoordinatenBei(XY) ───┘ │ │ │ │
├ Registrieren(Quadrat) ◀─XY─┘ │ │ │
│ └ Un-Registrieren() ◀─────XY───┊──┘ │
├ Alle Prüfen() ►────────┐─▷────│─────┘
└ Darstellung erneuern() ─┘ ◁───┘
└ Färben(), Gratulation()
Wie das Gitter überprüft, ob auch am Rand rote Kanten liegen? Statt weiteren Code für den Rand zu basteln, wird das Gitter mit voll-roten Quadraten ohne graphische Repräsentation außerhalb das Gitters vorbelegt. Das hat den kleinen Nebeneffekt, das auch out-of-bounds-Fehler im Prüfalgorithmus vermieden werden, da ja z.B. bei negativen Gitterkoordinaten -1 stets ein solches „virtuelles“ Quadrat liegt.
Wie man also sieht, kann man an diesem Spiel schon einige lustige Code-Spar-Methoden benutzen. Eigentlich sparen sie nicht nur Code, sondern auch Nachdenken, wenn man sie „sieht“.
Javascript Umsetzung
JS-Closures habe ich in letzter Zeit immer mehr zu schätzen gelernt. (Man muss in PHP übrigens auch nicht mehr lange darauf verzichten) Sie lassen den Programmierer Funktionen, also mehr oder weniger Code, wie ein String oder eine Zahl an andere Funktionen übergeben oder in Variablen spichern, sodass mit anonymen Funktionsobjekten als Closures in JS eigene Kontrollstrukturen definiert werden können, wie diese zweifache for-Schleife, um über Koordinaten bzw. Zweidimensionales zu loopen:
function loopXY(w,h,cb) {
for (var x=0;x<w;x++) {
for (var y=0;y<h;y++) {
cb(x,y);
}
}
}
var m=[];
loopXY(5,7,function(x,y){
m.push("("+x+","+y+")");
});
alert(m);
Wie man sieht stehen in Javascript in den Closures alle äußeren Variablen zur Verfügung. Das wiederholte verwenden des Namens einer äußeren Variable führt trozdem noch dazu, dass in der Closure diese lokal verwendet wird und außen der alte Wert erhalten bleibt. Ein bischen gewöhnungsbedürftig ist die Verwendung von this in JS. Im oben gezeigten Code würde z.B. in der Schleife this auf window zeigen. Das lässt sich mit der Function.call oder der Function.apply-Funktion kompensieren, wie in diesen Code-Schnippseln für Event-Handler.
Für die Erstellung von Objekten (außer reinen Datenspeichern, die mit {} einfach erstellt werden können) verwende ich folgende Grundstruktur:
function Square(id) { // constructor
this.id=id; // Eigenschaften initialisieren
}
(function(){
var p=Square.prototype; // shortcut zum Prototype
p.setId=function(id) { // einfacher Setter
this.id=id;
return this; // macht Setter chainable
};
var privat; // kann nur von den Objektmethoden gesehen werden
function privatauch() {} // dito
})();
var s=new Square (3);
Allerdings bin ich mir nicht sicher, ob das wirklich besser ist, als alles in Konstruktoren zu packen.
Der Code des Onlinegames ist vielleicht nicht ganz so interessant zu lesen, wie es war ihn zu erstellen, aber ich denke, hinein schauen lohnt sich. Ich bin natürlich immer interessiert an weiteren Javascript-Techniken und Tipps zur Code-Gestaltung.
Processing: 3D-Koch-Kurve mit Sierpinski-Dreieck
Nachdem ich mich jetzt mal an Processing heran gewagt habe, habe ich auch gleich mal einen fraktalen Körper basteln müssen. Es handelt sich um eine Art dreidimensionale Koch-Schneeflocke.
Die Koch-Schneeflocke an sich ist eigentlich recht simpel, habe ich schon in Logo und PHP implementiert. Es wird eine Linie jeweils durch eine Linie mit einem Dreieck darin ersetzt. Auf den Raum übertragen heißt das dann eine Dreieckfläche bekommt einen Tetraeder eingesetzt. Dies wird dann mit den Flächen des Tetraeders rekursiv wiederholt, sodass dann ungefähr so etwas entsteht:
Es entsteht eigentlich eine etwas andere Form, die allerdings nicht sehr interessant anzusehen ist, nämlich ein Tetraeder, der in viele kleine Tetraeder zerlegt ist. Damit der strenge Tetraeder etwas aufgelockert wird, habe ich die neuen Tetraeder immer um 70% skaliert. Es sind also keine Tetraeder mehr, sondern, je tiefer die Rekursion geht, immer schiefere Pyramiden.
Außerdem habe ich nicht mit nur einem Dreieck begonnen, sondern mit einem Tetraeder, sodass ein Körper ensteht, ähnlich wie wenn man in 2D mit dem Dreieck beginnt. Bei 6 Rekursionsschritten ergeben sich dann 66*4 = 186 624 Dreiecke. Die werden dann von Processing z.B. mit 7%iger Transparenz gerendert, damit es etwas schöner aussieht und so kann dann dieses Video entstehen:
Interessant ist eigentlich auch, dass der Rest, der vom ursprünglichen Dreieck bleibt, wenn man die ganzen Tetraeder heraus nimmt, genau dem Sierpinski-Dreieck entspricht. So sieht der Code aus:
fraqTriang trs[]=new fraqTriang[4];
void setup(){
size(640, 480, P3D);
noStroke();
fill(150,150,150,20);
int bigrad=200;
int req=6;
PVector A=new PVector(-bigrad,0,0);
PVector B=new PVector(bigrad/2,0,-173.21);
PVector C=new PVector(bigrad/2,0,173.21);
PVector D=new PVector(0,-bigrad*(sqrt(6)/3),0);
trs[0]=new fraqTriang(A,B,C,req);
trs[1]=new fraqTriang(A,D,B,req);
trs[2]=new fraqTriang(A,C,D,req);
trs[3]=new fraqTriang(B,D,C,req);
}
void draw(){
background(255);
lights();
float winkel=(mouseX/float(width))*TWO_PI;
float xpos=cos(winkel);
float ypos=sin(winkel);
float radius=300.000;
camera(xpos*radius, mouseY, ypos*radius, // eyeX, eyeY, eyeZ
0.0, -50.0, 0.0, // centerX, centerY, centerZ
0.0, -1.0, 0.0); // upX, upY, upZ
for (int i=0;i<trs.length;i++) {
trs[i].display();
}
//saveFrame("frames/koch3d-####.png"); //uncomment to record
}
class fraqTriang{
PVector PointA;
PVector PointB;
PVector PointC;
fraqTriang recTris[]=new fraqTriang[6];
int rec;
float scaling;
fraqTriang(PVector A,PVector B,PVector C, int recursion){
scaling=0.7;
PointA=A;
PointB=B;
PointC=C;
rec=recursion;
applyRecursion ();
}
void applyRecursion () {
if (rec!=0) {
PVector PointAB2=PVector.add(PointA,PointB);
PointAB2.div(2);
PVector PointAC2=PVector.add(PointA,PointC);
PointAC2.div(2);
PVector PointBC2=PVector.add(PointB,PointC);
PointBC2.div(2);
PVector PointZ=PVector.add(PointA,PointB);
PointZ.add(PointC);
PointZ.div(3);
PVector PointAB=PVector.sub(PointA,PointB);
PVector PointAC=PVector.sub(PointA,PointC);
PVector PointH=PointAB.cross(PointAC);
PointH.normalize();
PVector PointAAB2=PVector.sub(PointA,PointAB2);
float a=PointAAB2.mag();
float pheight=a*(sqrt(6)/3)*scaling;
PointH.mult(-pheight);
PVector PointZH=PVector.add(PointZ,PointH);
recTris[0]=new fraqTriang(PointA,PointAB2,PointAC2,rec-1);
recTris[1]=new fraqTriang(PointB,PointBC2,PointAB2,rec-1);
recTris[2]=new fraqTriang(PointC,PointAC2,PointBC2,rec-1);
recTris[3]=new fraqTriang(PointZH,PointAC2,PointAB2,rec-1);
recTris[4]=new fraqTriang(PointZH,PointAB2,PointBC2,rec-1);
recTris[5]=new fraqTriang(PointZH,PointBC2,PointAC2,rec-1);
}
}
void display () {
if (rec==0) {
beginShape();
vertex(PointA.x, PointA.y ,PointA.z);
vertex(PointB.x, PointB.y ,PointB.z);
vertex(PointC.x, PointC.y ,PointC.z);
endShape(CLOSE);
} else {
for (int i=0; i<recTris.length;i++) {
recTris[i].display();
}
}
}
}
Man sieht dem Code an, wie schnell man mit Processing Graphiken erstellen kann, ohne sich mit komplizierteren APIs herumzuschlagen. Durch die vielen Beispiele, die Processing beiliegen und die übersichtliche API-Dokumentation kann man innerhalb von kurzer Zeit schon recht hübsche Ergebnisse erzielen. Viel Synatax muss man auch nicht lernen, da die Processing-Synatx mehr oder weniger der von Java entspricht.













