Bei der Aufzeichnung unseres aktuellen Trainings kam Saban auf mich zu, da seine 3D-Versuche mit Rundungsfehlern zu kämpfen hätten. Und in der Tat, Math.sin(Math.PI) ergibt nicht die zu erwartende 0. Aber warum ist dieses Problem in älteren Projekten nie aufgefallen?
Meine Tests ergaben, dass Math.sin(Math.PI) nicht mehr nur 15 signifikante Stellen (wie z. B. auch Math.PI) sondern im aktuellen Flash Player ein paar Nachkommastellen mehr hat. Wenn ich die Genauigkeit nun einfach wieder auf das Verhalten älterer Flash Player ändere und Math.round(Math.sin(Math.PI)*1e15)/1e15 nutze, dann kommt auch wie erwartet 0 heraus. Eigentlich ist dieses Ergebnis ein gutes Zeichen, da die vom Flash Player verwendete Näherung für Sinus und Cosinus nun deutlich genauer zu arbeiten scheint (also mit mehr Stellen). Doch im Einzelfall kann diese Näherung auf Dauer zu Berechnungsfehlern führen, die es früher nicht gab – gerade bei umfangreichen 3D-Berechnungen sollte man das im Auge behalten.
Das Berechnen von Werten scheint sich aber auch an anderen Stellen seltsam zu verhalten. Bei Saban ergab beispielsweise trace(4.4 + 2.9) im Flash Player 10 den Wert 7.300000000000001. Woher auch immer die Nachkommastelle kommt. Und bei einem eigenen Versuch wurde aus 1.0000000000000005 (also der 5 auf der 16. Nachkommstelle) die Zahl 1.00000000000000004 (also eine 4 auf der 16. Nachkommstelle). Mit ActionScript 2 (also der alten AVM) passen die Werte jedoch auch im Flash Player 10 bzw. werden korrekt gerundet.
Hi,
so ähnlich verhält sich AS3 auch, wenn ich z. B. 1/197*197 rechne. Anstelle einer 1 kommt dann eine 0.9999999999999999 heraus. In einer Skala von 0-200 betrifft das folgende Zahlen: 49, 98, 103, 107, 161, 187, 196, 197.
Da man in AS3 beispielsweise Alphawerte nicht mehr mit 0-100% sondern mit einem Float von 0-1 angibt kann man so diesen errechneten Wert nicht wirklich verwenden um einen Event abzufeuern wenn der Alphawert genau 1 erreicht. Das Ganze kann man natürlich abfangen, indem man beispielsweise weiterhin mit Prozentwerten arbeitet, die man dann (um ggf. den Event abzufeuern) runden kann und wieder durch 100 teilt um das Ergebnis als Alphawert zu verwenden. Das Verhalten von AS1 und AS2 fand ich allerdings vorteilhafter da man direkt mit dem Ergebnis einer so simplen Rechnung arbeiten konnte ohne runden zu müssen.
Ich habe die Diskussion schon im Flashforum geführt. Da alle anderen Programmier- und Scriptsprachen, inkl. AS1 und AS2, dieses Verhalten nicht an den Tag legen gehe ich nach wie vor von einem Bug in AS3 aus. Natürlich muss man als Programmierer Ergebnisse ordentlich runden usw. aber eine Programmiersprache muss sich ja auch an einen gewissen Standard halten.
Gruss
Mark