Goldene Regeln für die Programmierung astronomischer Problemstellungen

 

Eine häufige Fehlerquelle beim Erstellen astronomischer Software ist z.B. die uneinheitliche Verwendung von Maßeinheiten. Dies ist sicherlich nur ein herausgegriffenes Beispiel, aber beim Betreiben einer Fehleranalyse wird man feststellen, daß man stets mit dieselben Fehlertypen konfrontiert wird. Aus diesem Grund sind hier ein paar Goldene Regeln für die Programmierung zusammengestellt. Sie sollen es dem Programmierer ermöglichen, Code zu schreiben, der weniger fehleranfällig, leichter zu warten und erweiterbar ist. Wir beschränken uns auf Hinweise mit ausdrücklichem Bezug auf die Programmierung astronomischer Problemstellungen.

1.    Vermeide die Berechnung der Quadratwurzel einer astronomischen Größe, wenn abzusehen ist, daß nur mit ihrem Quadrat weitergerechnet wird (Performance), insbesondere wenn diese Berechnung innerhalb einer Schleife steht.

2.    Verwende einheitliche Maßsysteme, z.B. m/sec/kg. Probleme können entstehen, wenn z.B. Geschwindigkeiten in m/s und Entfernungen in Lichtjahre oder AE angegeben werden. Die Ein-/Ausgabe sollte hingegen unbedingt im gebräuchlichen Maßsytem erfolgen; wenn jedoch eine Umrechnung erforderlich ist, dann ist sie unmittelbar nach der Eingabe bzw. vor der Ausgabe vorzunehmen.

3.    Optimiere einen Code nur, wenn es wirklich unvermeidlich ist. Ggf. können kritische Stellen mit einem Profiler identifiziert werden. In der astronomischen Programmierung können mehrfach ineinander verschachtelte Schleifen auftreten; sie sind am ehesten Ansatzpunkt für gezielte Optimierungen. Heutzutage kommt man meist ohne das Optimieren aus ("optimiere nie auf Vorrat").

4.    Vermeide die Verwendung der Gravitationskonstanten G bei der Auswertung der Bewegungsgleichungen, wenn das das Produkt µ=G*(M+m) bekannt ist, da letzteres mit höherer Genauigkeit bekannt ist als die Gravitationskonstante selbst.

5.    Man überlege sich, ob man wirklich Kräfte berechnen muß und nicht mit Beschleunigungen auskommt. Ansonsten multipliziert man mit Massen, die später wieder herausdividiert werden.

6.    Beachte, daß bei den inversen trigonometrischen Funktionen (arcsin, arctan, etc.) für das korrekte Ergebnis der Quadrant des Arguments berücksichtigt werden muß. Dies macht evtl. mehrere Fallunterscheidungen erforderlich. U.U. muß zusätzlich geprüft werden, ob das Argument überhaupt zulässig ist, z.B. arctan(x/y) für y=0. Sinnvollerweise geschieht dies einmalig in einer Funktion oder Methode.

7.    Die Division mit sehr kleinen Zahlen führt zu vergleichsweise großen Rechenungenauigkeiten und ist sehr oft ein Indikator für einen Fehler oder Schwachpunkt im verwendeten Algorithmus oder für einen ungünstig gewählten Rechenweg innerhalb dessen. Auch der Gültigkeitsbereich des Algorithmus sollte in diesem Fall überprüft werden.

8.    Verwende auf Plattformen mit FPU (math. Coprozessor, alle aktuellen PC's besitzen einen) nach Möglichkeit für Gleitkommazahlen denjenigen Datentyp mit 10 Byte (z.B. Java: double, C/C++: long double, Delphi: extended). Die FPU arbeitet intern ausschließlich mit diesem Typ. Die Verwendung von anderen Gleitkommatypen, z.B. 'single' (4 Byte) führt neben Genauigkeitsverlust zur niedrigerer Performance, da andere Zahlenformate in den 10-Byte-Typ konvertiert werden müssen. Die Verwendung von weniger genauen Zahlentypen auf Systemen mit FPU führt ausdrücklich *nicht* zu schneller ausführbarem Code! Hinweis für C: Zur Vermeidung von Portabilitätsproblemen kann für den verwendeten Gleitkommatyp ein 'typedef' gesetzt werden.

Abbildung: Das Rechnen mit Fließkommazahlen erfolgt intern oft mit 10 Bytes. Ein einzelnes Bit ist für das Vorzeichen (+/-) der Zahl reserviert, weitere 11 Bits sind für den Exponenten zuständig, sprich: die Position des Kommas. Die restlichen Bits repräsentieren die eigentliche Zahl.

9.    Achte auf Skalierbarkeit und Wiederverwendbarkeit von Funktionen, sofern eine erneute Verwendung bereits abzusehen ist (etwa eine Bibliothek), z.B. sollte eine Funktion zum Lösen eines linearen Gleichungssystems nach Gauss so ausgelegt sein, daß man ein Gleichungssystem beliebiger Dimension lösen kann. Dies erfordert dynamische Datenstrukturen.

10.    Vermeide nicht nur Divisionen durch 0, sondern überlege bei jeder Division zusätzlich, woher und unter welchen Umständen eine 0 in den Nenner gelangen könnte. Möglicherweise liegt schon darin ein Fehler vor. Dieser Gedanke sollte den Programmierer auf seinen gesamten Entwicklungsprozeß begleiten. Der Erkenntnisgewinn (Fehlererkennung) kann beachtlich sein. Die gleiche Betrachtung gilt auch für negative Argumente in Wurzeln oder Logarithmen.

11.    Bahnelemente haben verschiedene Darstellungen, z.B. sind die Angaben der Mittleren Anomalie und des Periheldurchgangs für elliptische Bahnen äquivalent zueinander. Man sollte sich für den gängigsten Parametersatz entscheiden oder dem Benutzer des Programms mehrere Auswahlmöglichkeiten zur Bahndateneingabe/-ausgabe anbieten. Im letzteren Fall sollten die Auswahlmöglichkeiten unzweideutig sein (die gleichzeitige Eingabe zweier äquivalenter Bahnelemente ist auszuschließen). Zudem muß man sich bei der Bezeichnung der Bahnelemente über ihre Bedeutung im Klaren sein, so z.B. sind die Länge des Perihels und das Argument des Perihels zwei völlig verschiedene Größen.

Abbildung: Der Zeitpunkt des Periheldurchgangs und die Mittlere Anomalie sind zwei verschiedene, aber gleichwertige Möglichkeiten zur Angabe der momentanen Position eines Himmelskörpers auf seiner elliptischen Bahn. Beide Größen können zwar durch einfache Berechnungen ineinander überführt werden, jedoch findet man in der Literatur entweder die eine oder die andere Größe.

12.    Besondere Aufmerksamkeit ist den Bezugssystemen zu widmen: man veranschaulich sich z.B. den Unterschied zwischen baryzentrischen und heliozentrischen Koordinaten, oder ob Bahndaten sich auf Equinox of day oder 2000.0 beziehen. Zu jedem Zeitpunkt der Programmentwicklung müssen diese Bezugssysteme eindeutig definiert und vollständig verstanden sein. Bei Variablennamen kann man z.B. Suffixe verwenden, die das Koordinatensystem oder Maßeinheit genauer angeben. Das hilft, die Übersicht zu behalten.

13.    Jede Rechnung ist maximal nur so gut wie die ihr zugrunde liegenden Eingabedaten. Es ist, besonders für Anwendungen, die Präzision erfordern, zu beachten, daß die für Amateurastronomen zugänglichen Daten oftmals höheren Anforderungen nicht gerecht werden. Erst wenn die Qualität der Eingabedaten sichergestellt ist, kann eine Anwendung sinnvoll getestet werden.

14.    Rechengenauigkeiten: Summen bildet man nach Möglichkeit beginnend mit den kleinsten Summanden, da sonst Auslöschung von Stellen auftreten kann. Bei numerisch problematischen Funktionen (die nahe an Singularitäten ausgewertet werden sollen) hilft oft die Entwicklung in eine Taylorreihe weiter.

 

[zurück...]