Starwars – Nur reine Fiktion?

09. September 2011

Ich glaube nicht das Starwars nur reine Fiktion ist. Denn ich habe immer zunehmender das Gefühl, das viele Programmierer direkt bei Meister Yoda in die Schule gegangen sind. Wie sonst könnte ich mir folgenden Code erklären?


Also in der deutschen Synchronisation:

Wenn null nicht die Verbindungsdose ist

Das ist Fürchtervoll und Grauenlich…

Weiterlesen »

Agile Softwareentwicklung…

09. September 2011

…hat nicht nur Vorteile:

Primzahlen mal anders…

09. September 2011

Mir war langweilig und ich habe versucht ein kurzes Programm zu schreiben, welches mir die ersten 1000 Primzahlen ausgibt. Das Kürzeste was mir eingefallen ist, habe ich mit Perl umgesetzt:

map{print"$_\n"if(1x$_)!~/^(11+?)\1+$/}(2..1000)

Kann das jemand unterbieten?

Kilobyte

25. September 2010

Was ist der Unterschied zwischen einem Physiker und einem Programmierer?

Der Physiker glaubt, 1KByte waeren 1000 Bytes.

Ein Programmierer glaubt, 1km waeren 1024m…

Innere Werte

01. September 2010

Folgende kleine und gruselige “extension method” für C# habe ich aufgetan.

    public static Exception GetInnermost(this Exception ex)
    {
        Exception ActualInnerEx = ex;
        while (ActualInnerEx != null)
        {
            ActualInnerEx = ActualInnerEx.InnerException;
            if (ActualInnerEx != null)
                ex = ActualInnerEx;
        }
        return ex;
    }

Diese Methode soll die innerste Exception einer abgefangenen Exception ermitteln. Hier sieht man mal wieder wie umständlich etwas im Grunde sehr einfaches umgesetzt werden kann.

Übung: Wie könnte man diese Methode besser und schöner gestalten?

Weiterlesen »

Sequenzialisierte Schleife

23. April 2010

Wie wäre es damit?

for( int i = 1 ; i <= 3 ; i++)
{
    if(i==1) {...}
    else  if(i==2) {...}
    else if(i==3) {...}
    else {...}
}

Sowas kann man sich wirklich nicht selbst ausdenken :)

Alles fürn Arsch…

07. Oktober 2009

Hier eine netter Methodennamen, den mein Kollege just in unserem “Kot” gefunden hat:

get_ass_flag();

Endlich mal jemand hier der das, was er über die Software denkt auch mal umsetzt :)

Solange Du Deine Füße unter meinen Tisch stellst…

06. Juli 2009

…bzw. solange Du Dich von mir ableitest, machst Du was ich sage!

Ich finde, dies ist mal wieder ein wunderschönes Beispiel dafür, wie Objektorientierung nicht funktioniert! Gefunden von meinem Kollegen in freier Wildbahn (Namen wurden von der Redaktion geändert :) )

Image-37

Was wir von einer Klotür lernen können…

01. Juli 2009

In der Informationstherorie ist die kleinste mögliche Informationseinheit ein Bit! 0 oder 1, An oder Aus, Offen oder Zu, Wahr oder Falsch. Alles mögliche Darstellungsformen, genauergesagt Interpretationsformen dieser minimalen Informationseinheit. Eine funktionierende Klotür kann nur Offen oder Verschlossen sein. Aber es existieren mehrere Interpretationsmöglichkeiten, die sich auf diesen Zustand beziehen. Wenn ich aufs Klo möchte, interessiert mich natürlich ob eine Kabine Frei oder Besetzt ist, da ich natürlich eine dieser Kabinen verwenden möchte. Befinde ich mich bereits in einer Kabine, so interessiert mich nicht mehr ob diese Kabine frei ist, denn ich weiss ja das sie es nicht mehr ist, ich bin ja schliesslich drin. Aber mich interessiert nun, ob die Tür Verschlossen oder Offen ist. Ich möchte ja schliesslich meinen Geschäftigkeiten ungestört nachgehen. Somit haben wir mehrere Interpretationsmöglichkeiten des Türzustandes. Dieser ist von dem Zustand abhängig, ob ich mich vor oder hinter der Tür befinde.

Wenn wir die Brücke jetzt zur Softwareentwicklung schlagen, könnte man das Vor bzw. Hinter der Tür als “Ich verwende eine Komponente” bzw. als “Ich entwickle eine Komponente” verstehen. Der Komponentenentwickler wird sich sicherlich für den Zustand interessieren, das eine Kabine besetzt ist, denn dann muss er mit den  ”Daten” irgendwas anstellen. Was kümmern ihn also die leeren Kabinen?

Jemand der diese Komponente jedoch verwendet, den interessiert nicht ob eine Kabine bereits besetzt ist. Ihn interessieren besetzte Kabinen nicht wirklich. Jemand der schon einmal enorm dringend aufs Klo musste, wird das nachvollziehen können. Uns interessieren in diesem Moment nicht die 15 Kabinen die Besetzt sind, uns interessiert genau die Kabine die in dem Moment frei ist.

Dies ist der Grund, warum wir in diesem Fall an der Komponenten-Schnittstelle kein Flag zur Verfügung stellen sollten, welches Kabine.IstBesetzt heisst. Dieses Flag sollte stattdessen Kabine.IstFrei heissen. Denn das interessiert den Anwender an dieser Komponente.

Der Komponentenentwickler sollte aber Intern mit dem Zustand arbeiten, den er am Häufigsten braucht (was hier der Zustand Kabine.IstBesetzt sein dürfte). Wie lösen wir dieses Dilemma? Ganz einfach, das Zauberwort heisst Kapselung. Nehmen wir als Beispiel einmal C# als Zielsprache. Dort können wir mit dem IstBesetzt intern arbeiten, bieten aber ein Property IstFrei an der Schnittstelle an:

Kabine.cs

Somit arbeitet jeder mit der Interpretation, die für ihn am Besten geeignet ist!

Diese Betrachtungsweise ist natürlich nicht nur auf Flags beschränkt! Dies gilt für alle Daten, Methoden und Properties die eine Schnittstelle nach außen offenlegt.

Zahlenvergleich

26. Juni 2009

Heutzutage wird es einem sehr leicht gemacht große Datenbestände zu sortieren. Es gibt vorgefertigte, hoch performante Methoden die lediglich die zu sortierenden Daten und einen Zeiger/Referenz auf eine Vergleichsmethode erwarten. Diese Methode ist im Normalfall ganz einfach gestrickt. Sie bekommt einfach zwei Parameter vom Typ der zu sortierenden Daten. Die Methode hat nichts weiter zu tun als diese Daten auszuwerten. Wenn der erste Parameter als “größer” zu bewerten ist, gibt die Methode einen positiven Wert, bei “kleiner” einen Negativen und bei Gleichheit eine 0 zurück.

Betrachten wir hier einmal den Spezialfall eines Integervergleichs. Eine Methode dafür sieht wie folgt aus:

Image

Nun gibt es aber eine Reihe von Menschen, die an einem aktuten Nanosekundenverschwendungssyndrom leiden. Bedingt durch meine technische Ausbildung, muss ich mich selbst hier dazu zählen.
Um Laufzeit zu sparen, könnte man nun auf die Folgende, doch sehr naheliegende Version dieser Methode kommen:

Image

Wenn a größer als b ist, so gibt diese Methode einen Wert größer 0, bei a < b einen negativen Wert und bei a = b eine 0 zurück.

Aber stimmt das Wirklich? Immer?

Wahrscheinlich ist die Frage nur mit Nein zu beantworten, denn sonst hätte ich mir sicherlich nicht die Mühe gemacht diesen Artikel zu schreiben. Aber woran krankt es denn nun bei dieser Lösung?

Das Problem welches wir in diesem Fall haben, ist die Beschränkung des Wertebereiches für einen Ganzahlwert. Rein mathematisch betrachtet ist die Formulierung korrekt. Geben wir den Kindern einmal Namen: Sei min der kleinste Wert und max der größte Wert den unsere Ganzzahl annehmen kann. Was passiert nun intern, wenn wir zu max noch eine 1 hinzuaddieren? Es kommt zu einem Überlauf und die Variable kippt auf den Wert min. Dies wird uns bei dieser Lösung zum Verhängnis. Betrachten wir einmal folgenden Aufruf:

Compare( max, min );

Wir erwarten hier, das die Methode einen Wert größer 0 zurück gibt. Wir erhalten jedoch -1. Dies lässt sich auch leicht nachvollziehen. Gehen wir mal von einer 32 Bit breiten Variablen aus. Diese hat einen Wertebereich von -2147483648 bis 2147483647. Wenn wir jetzt min von max abziehen, erhalten wir 2147483647 – (-2147483648) was nach Adam Riese nun 4294967295 ergibt. Das ist in Hex: 0xFFFFFFFF. Was bedeutet alle Bits sind gesetzt. Dies entspricht aber gerade (in der 2er Komplementdarstellung) die -1.

Jetzt könnte uns ja interessieren in wievielen Fällen dies passiert, um eine Abschätzung des Fehler zu geben. Dazu müssen wir uns der (sowas braucht man nur in der Schule-)Mathematik zuwenden. Zuerst müssen wir die Bedingung für gültige Vergleiche aufstellen. Das ist ziemlich einfach. Es dürfen am unteren und oberen Rand keine Überläufe stattfinden, da sonst das Vorzeichen wechselt. Daraus ergibt sich folgende Bedingung:

Image

Wir haben auch noch ein paar Randbedingungen die wir (trivialerweise) einhalten müssen:

Image

Ich möchte hier den allgemeinen Fall für eine n-Bit Breite im 2er Komplement dargestellte Zahl betrachten. Somit ergeben sich die Grenzen für min und max wie folgt:

Image

Nun können wir loslegen. Da a und b zwei unabhängige Variablen sind, kann für jeden Wert b, a Werte zwischen min und max annehmen. Wir haben also eine Matrix über a und b. Betrachten wir erst einmal die gültigen a Werte für ein gegebenes b. Dafür formen wir einfach die ursprüngliche Ungleichung nach a um und erhalten:

Image

Da aber a wegen der oben genannten Randbedingungen auch im Bereich [ min, max ] liegen muss, müssen wir die Grenzen ebenfalls auf diese Grenzen beschränken. Somit erhalten wir folgende Ungleichung:

Image

Da es sich um diskrete Werte handelt können wir nun alle möglichen gültigen Werte für a für ein gegebenes b berechnen:

Image

Uns interessieren allerdings die ungültigen Werte für a. Somit müssen wir von der Gesamtanzahl einer Zeile unsere gültigen Subtrahieren:

Image

Nun die Klammern auflösen und zusammenfassen:

Image

Somit erhalten wir die Anzahl von ungültigen Werten in einer Matrixzeile. Nun müssen wir das ganze nur noch über alle Matrixzeilen aufzummieren:

Image

Diese Formel gibt uns somit an, für wieviele Werte die Vergleichsmethode fehlschlägt. Aber wie kommen wir denn hier nun weiter? Wir haben Maxwertbildungen in einer Summe. Uffz… Nun hallen mir zum ersten mal wieder – nach sehr langer Zeit – die Worte meines Mathematikprofessors in den Ohren…

Sie dürfen keine Skrupel haben Beträge und Maximalwertbildungen in Fallunterscheidungen zu betrachten!

Ok Herr Engels. Dann mal los: Da es sich hier um einfache Maximalwertbildungen handelt, können wir das soger mit ein wenig Überlegung auch ganz einfach durchführen. Dazu ziehen wir die Summe einfach erstmal in drei Teile auseinander:

Image

Betrachten wir mal exemplarisch die 2. Summe. Wir können die Maximalwertbildung ganz einfach auflösen indem wir uns überlegen, für welche b einmal min bzw. b + min verwendet wird. Wann ist also min > b + min? Ganz einfach dann, wenn b < 0 ist. Somit müssen wir die Summe nur in zwei Teile aufteilen. Einen Teil für die negativen b und einen für b >= 0. Das sieht in diesem Fall dann wie folgt aus:

Image

Hier können wir wieder die 2. Summe auseinanderziehen. Auf diese Weise zerlegen wir auch die Zweite Maximalwertsumme. Wenn dann alles in der Ursprungsgleichung eingesetzt wird, kürzt sich eine Menge raus. Folgend also die einzelnen Schritte:

Image

Mit der folgenden Formel, die man in einem durchschnittlichen Formelwerk der Mathematik findet, können die Summen aufgelöst werden:

Image

Somit ergibt sich dann für die Anzahl der ungültigen Wertkombinationen die Formel:

Image

Uns interessiert aber wieviele Kombinationen bezogen auf alle möglichen Kombinationen fehlschlagen. Dazu müssen wir diesen Wert lediglich durch die Anzahl aller möglichen Kombinationen teilen:

Image

Nun können wir für min und max unsere Definitionen von oben einsetzen. Somit erhalten wir nach ein wenig Rechnerei folgendes Ergebnis:

Image

Hier können wir bereits den Wert n für die Bitbreite einsetzen. Aber wir sollten doch lieber einmal versuchen alles zu Vereinfachen. Macht man sich die Mühe und multipliziert das alles schön aus und fast zusammen, so kommt ein doch unerwartetes Ergebnis heraus:

Image

Das bedeutet, das diese Methode unabhängig vom darstellbaren Wertebereich stets in 25% aller Fälle falsch ist… Ups…

Dies ist – wie ich finde – ein sehr schönes Beispiel dafür, wie man sich schnell selbst ganz einfach eine Grube graben kann, nur weil man denkt es ganz geschickt und im “vorbeigehen” besser zu machen. Ausserdem zeigt es, wieviel Spass man mit einer Methode haben kann, die kaum kürzer sein könnte.