Float grobe Ungenauigkeit, Wer ist Schuld? Assembler oder C

Fragen zu allen anderen Programmiersprachen.
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Float grobe Ungenauigkeit, Wer ist Schuld? Assembler oder C

Beitrag von Macros »

Hi liebe PBler,

Mit meinem letzten Problem konnte mir leider niemand weiterhelfen,
aber nach längeren Herumprobieren hab ich es dann doch noch hinbekommen.
Die Lösung editiere ich sobald ich zeit hab in meinen vorigen Beitrag hinein.

Jetzt stehe ich vor einem neuen und aus meiner Sicht sehr seltsamen Problem:
Teste ich meine Funktion mit einer selbst geschriebenen Testbench, treten Ungenauigkeiten auf.
Eigentlich klar bei Fließkomma Berechnungen... Aber meine Testbench produziert korrekte Ergebnisse.
Als ich der Sache auf den Grund gegangen bin, musste ich feststellen, dass sich die Ungenauigkeiten immer ab einer bestimmten Potenz zeigen.

Ist das Ergebnis der Berechnung 1.234567890123_45 treten ab dem Unterstrich Fehler auf.
(normale Float Ungenauigkeit würde ich sagen)
Ist das Ergebnis 1.23_456789012345e-15 treten die Fehler viel früher auf.
Da die Exponenten bei Fließkomma Variablen doch getrennt gespeichert werden, bringt mich das gerade zum verzweifeln.
(Ergebnisse mit so kleinen Exponenten sind wahrscheinlich)
Man kann mich auch gerne weiterleiten zu Leuten die sich mehr mit solchen Dingen beschäftigen als der durchschnittliche PB Nutzer

Falls sich jemand das mal genauer anschauen will:
  • Unter http://web254.rshost.de/PB/CASM/C.zip findet man den C und Assembler Code.
    mit den Befehlen "make clean && make" kann man in der Konsole daraus die calc Executable erzeugen.
  • Unter http://web254.rshost.de/PB/CASM/Testbench.zip die Testbench
    Wer mir nicht traut kann sie nochmal aus dem Code kompilieren ;) Ausführen sollte man sie über ./Testbench auf der Konsole.
    Dann sieht man nämlich die Ausgaben und Fehlermeldungen die sie macht.
    Im Moment ist sie so eingestellt, dass in ca 70% der Fälle Fehler unter den 200 Testwerten auftreten
Wäre toll, wenn mich jemand aus meiner Verwirrung retten kann,
oder mir sogar erzählen, wie man das komische Problem beheben kann.

Grüße
Macros
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von NicTheQuick »

Habe mir deinen Code nicht angeschaut, aber kann es sein, dass die Fehler schon bei irgendwelchen Zwischenschritten auftreten? Ich bin kein Meister der Numerischen Optimierung, aber oftmals gerät man bei Zwischenschritten an die Grenzen der Fließkommagenauigkeit und summiert diese bis zum endgültigen Ergebnis auf.

///Edit:
Bei ein solchen Formel:

Code: Alles auswählen

C_0 = 2 * #PI * #e_0 * radius * (1 + (radius * (abstand * abstand - radius * radius)) / (abstand * (abstand * abstand - abstand * radius - radius * radius)))
würde ich auf Nummer sicher gehen und bei allen konstanten Werten einen Punkt anhängen, damit sie klar Fließkommazahlen sind.

Code: Alles auswählen

C_0 = 2. * #PI * #e_0 * radius * (1. + (radius * (abstand * abstand - radius * radius)) / (abstand * (abstand * abstand - abstand * radius - radius * radius)))
Oder versuch mal diesen Code:

Code: Alles auswählen

abstandRadiusSqr.d = abstand * abstand - radius * radius
C_0 = 2. * #PI * #e_0 * radius * (1. + (radius * abstandRadiusSqr / (abstand * (abstandRadiusSqr - abstand * radius)))
Der ASM-Code, der ja die Funktion 'calc' beinhaltet, macht zwangsweise auch viele Zwischenschritte.
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von Macros »

Der Purebasic Code erzeugt korrekte Vergleichswerte.
Ich hab bei den Unterschieden einen wissenschaftlichen Taschenrechner der nicht an Double usw. gebunden ist zum Vergleich herangezogen,
Pb hatte "Recht" ( Wer sonst xD)

Würde ein Fehler, eine Ungenauigkeit mitgeschleift, würde die sich doch auch bei großen Zahlen zeigen.
Die Grenzen des Exponentenfelds einer Floatzahl sind an keiner Stelle der Formel ausgereizt
(klein werden die Ergebnisse erst nach Multiplikation mit e_0)
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von STARGÅTE »

Ist das Ergebnis der Berechnung 1.234567890123_45 treten ab dem Unterstrich Fehler auf.
(normale Float Ungenauigkeit würde ich sagen)
Float-Ungenauigkeit tritt schon bei 1.2345678_9012345 ein!
Da die Exponenten bei Fließkomma Variablen doch getrennt gespeichert werden, bringt mich das gerade zum verzweifeln.
Jo das stimmt schon, allerdings gehts bei dem Exponenten in der Float nicht um deine e-15 !!
Sonden um den Exponenten einer 2er Basis ...
Float -> Exponent hat 8Bit -> 127 Zahlen -> 2^127 -> im bereich 1e38

Soll heißen, 18.4 wir nicht genauso gespeichert wie 0.184 nur mit einem anderen Exponenten .
Sonden bei 0.184 wird die ganze Mantisse neu erstellt.

Code: Alles auswählen

f.f = 18.4
Debug f

Bin$ = RSet(Bin(PeekL(@f),#PB_Long),32,"0")
Bin$ = InsertString(InsertString(Bin$,"  ", 10),"  ", 2)

Debug Bin$
Debug "VZ Exponent  Mantisse "

f.f = f*1e-2
Debug f

Bin$ = RSet(Bin(PeekL(@f),#PB_Long),32,"0")
Bin$ = InsertString(InsertString(Bin$,"  ", 10),"  ", 2)

Debug Bin$
Debug "VZ Exponent  Mantisse "
Gleiche Zahlen mit unterschiedlichen 10er Exponenten werden also unterschiedliche Ergebnisse bringen.
Somit hängen beide doch irgendwie zusammen!

Das deine Zahl jedoch schon nach 3 Stellen ungenau wird, liegt vermutlich im Rechenweg! (Fehlerfortpflanzung)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von Macros »

STARGÅTE hat geschrieben: Float-Ungenauigkeit tritt schon bei 1.2345678_9012345 ein!
Ok erwischt, das war übertrieben ;)
Aber die Genauigkeit geht bis zur letzten Stelle, die Float exakt speichern kann.
Das liegt daran, dass die FPU in der CPU mit 80 Bit Genauigkeit rechnet,
und das korrekte Endergebnis dann in die Float Variable zurückgeschrieben wird.

Jedoch der Punkt bleibt bestehen. Die Mantisse ändert sich,
aber das tut sie ja auch bei der Berechnung im PB Programm.
Eine so grobe Ungenauigkeit darf es meiner Meinung nach nicht geben, da die Berechnung im Assemblerprogramm auch komplett in der FPU läuft.
Und das selbe Argument wie oben: Ungenauigkeiten würden sich ja auch bei größeren Eingabezahlen in der Matisse ausbreiten.

Danke für die schöne Veranschaulichung vom Aufbau einer Float
Bild
Benutzeravatar
alter Mann
Beiträge: 201
Registriert: 29.08.2008 09:13
Wohnort: hinterm Mond

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von alter Mann »

Win11 64Bit / PB 6.0
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von Macros »

Danke, das Floating Point Control Word war schon mal ein guter Tipp.
Nur finde ich nirgendwo eine ausführliche Doku über den Aufbau.
Ich müsste es ja von meinem Assembler Programm aus setzen.
Mein Tutor für die Aufgabe hat mir soeben gesagt, dass Ungenauigkeiten bei 10^-16 tolerabel sind...
Stimmt mir aber bei meinen Überlegungen zu. Dringlichkeit ist jetzt nicht mehr gegeben,
ärgern tuts mich immer noch ^^

Ein weiterer Grund lieber PB und FASM als C und NASM zu verwenden ;)
Bild
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von Helle »

Jetzt muss ich doch mal mitmischen :mrgreen: . Also: NASM ist natürlich unschuldig; ein Assembler arbeitet nur das ab, was ihn der Programmierer vorsetzt. Und calc.asm ist schlicht und einfach für Float geschrieben (32-Bit). Erkennbar auch an diversen dword-Inputs; ist halt nur Float (Double wäre qword). Ein dword in einer Rechenkette versaut jede angestrebte Double-Precision. Auch ist es ein Irrtum, die FPU würde automatisch mit 80-Bit-Precision rechnen (würde eh nichts nutzen, wenn der zu verarbeitende Wert nur als 32/64-Bit-Wert vorliegt). Test- und sonstige Programme dazu habe ich hier schon divers zum Besten gegeben; auch Rechnen mit 80-Bit.
Außerdem: Wenn nur die Grundrechenarten gefragt sind (wie hier), dann ran an SSE (Float) oder SSE2 (Double)! Wozu habt ihr Geld für dies beherrschende Prozis ausgegeben :lol: !?
Gruß
Helle
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Float grobe Ungenauigkeit, Wer ist Schuld? Assembler ode

Beitrag von Macros »

Aber sicher, ein bisschen Helles Geheimmischung wird die Suppe jetzt auch noch vertragen ^^
Das NASM wenig Schuld trifft ist mir klar, außer es setzt das Floating Point Control Word falsch.
Float stimmt, kein SSE(2) stimmt ebenfalls, nur ist das nicht meine Schuld, sondern die Übungsleitung,
die uns die Aufgaben von vor 10 Jahren vorlegt, und deshalb auch Lösungen von vor 10 Jahren will ;)
Also NASM, C, kein SSE, kein MMX und kein 64 Bit.

Zu Float muss ich sagen:
Da die Ausgabe auf 8 Stellen gekürzt wird, ändert ein Wechsel auf Floats in der Testbench nichts am Ergebnis in der Datei.
PB veranlasst also offensichtlich das Rechnen mit 64 oder 80 Bit Genauigkeit
Bild
Antworten