SAS-Rechengenauigkeit
Vermutlich bin ich der einzige Mensch auf der Welt, der ein Problem damit hat, dass SAS zu genau rechnet :-) Nichtsdestotrotz meine Fragestellung:
Ich habe ein SAS-Programm, das das gleiche Ergebnis liefern soll wie ein den gleichen Algorithmus implementierendes, aber in C geschriebenes Programm. In dem Algorithmus kommen mehrere Gleitkomma-Operationen vor. Da das C-Programm den Datentyp "float" verwendet, werden Gleitkommazahlen dort mit Single Precision berechnet und gespeichert (als 32Bit-Werte im IEEE-Format). Da SAS (in meinem Fall konkret: das Modul SAS/IML) intern mit Double Precision (64 Bit) rechnet, unterscheiden sich die Ergebnisse zwischen SAS und dem C-Programm (in der Regel ca. ab der 4. bis 5. Nachkommastelle).
Meine erste spontane Idee war, mein 64-Bit-Ergebnis mit den IEEE-Formaten auf 32 Bit zu kürzen. Damit komme ich dann allerdings nochmal auf ein anderes Ergebnis. Ich bin nicht wirlich fit in der binären Gleitkommarithmetik, aber ich vermute, dass es einen Unterschied macht, ob die eigentliche Berechnung mit 64 Bit durchgeführt wird und dann das Ergebnis auf 32 Bit gekürzt wird, oder ob gleich die komplette Berechnung mit 32 Bit erfolgt.
Der langen Rede kurzer Sinn: Ist es möglich, SAS dazu zu bringen, bei Gleitkomamoperationen nur mit Single Precision zu rechnen? (Idealerweise mit einer OPTION, die ich nach der kritischen Berechnung dann schleunigst wieder auf 64Bit zurücksetzen kann...)
- Anmelden oder Registrieren um Kommentare zu schreiben

Im DATA-Schritt mit LENGTH-Anweisung möglich
Mit der LENGTH-Anweisung kann man sowohl die Genauigkeit einzelner Variablen auf 4 setzen als auch für alle neu erzeugten numerischen Variablen die Länge auf 4 setzen:
Ob SAS dann genauso rechnet wie das C-Programm kann ich nicht sagen.
Es gibt zum Thema Fließkommaarithmetik folgende Artikel von SAS:
Wie das mit LENGTH in IML ist, kann ich leider nicht sagen.
Gute Idee, aber...
... leider komme ich damit wieder auf ein anderes Ergebnis. Habe es jetzt mit folgendem Programm ausgetestet:
DATA Test;
LENGTH ShortVar 4;
LENGTH LongVar 8;
ShortVar = 457*1000/6716; /* ergibt 68.046447754 */
LongVar = 457*1000/6716; /* ergibt 68.046456224 */
IEEE32Var = input(put(LongVar, IEEE4.), IEEE4.); /* ergibt 68.046455383 */
RUN;
Das C-Programm liefert für diese Berechnung einen Wert von 68.04646 (nicht gerundet, sondern nach der 5. Nachkommastelle abgeschnitten! Der exakte Wert liegt mir nicht vor, da ich die Zwischenergebnisse des C-Programms auch nur aus 2. Hand habe). Insofern stimmt das Ergebnis mit keinem der drei hier berechneten Ergebnisse überein...
IML rechnet übrigens generell mit Double Precision (Quelle: SAS OnlineDoc), und akzeptiert meines Wissens nach auch kein LENGTH- oder vergleichbares Statement.
Allgemeines über Rechengenauigkeit.
Hallo,
Ich kann zwar nicht direkt helfen, aber vielleicht sollten folgende Sachen bedacht: Man rechnet auf dem Rechner nicht auf einem Kontinuum, sondern auf einer endliche Menge von Werten. Das heißt:
- Rechnungen auf einen Rechner hängen auch von der Reihenfolge der Rechenschritte ab (
a+b+cnec+b+a). Diese Reihenfolge kann man zwar im C-Programm festlegen, aber was der Compiler dann rumoptimiert weiß man nicht (je nach Optimierungsgrad können andere Ergebnisse raus kommen). Von SAS weiß man das sowieso nicht.- Die Berechnung selbst wird immer mit einer Standardgenauigkeit durchgeführt, je nachdem, was für ein Prozessor man hat. Gerundet wird hinterher. Das heißt derselbe SAS oder C-Code kann auf verschiedene Rechnern verschiedene Ergebnisse habe.
Sprich: Sinnvolles Runden (auch der Zwischenergebnisse) hilft.
Als Literatur in Richtung Zahlendarstellung auf dem Rechner empfehle ich Schwetlick, Numerische Linear Algebra da ist das recht gut und anschaulich erklärt (auch für Nichtmathematiker).
Gruß _ULeh