Addition von double
-
Hallo,
ich hab das Problem das ich ein recht aufwändiges Programm in C++ geschrieben habe, an denen an manchen Stellen mit sehr großen Zahlen gerechnet wird (im Bereich von 500000).
Wenn ich da eine Subtraktion debugge merke ich, dass er bei long double bereits nach 4 Nachkommastellen abschneidet, welches eine zu große Ungenauigkeit ist.
In einem anderen Projekt führt er aber die Subtraktion mit den gleichen Datentypen problemlos durch, sodass ich glaube, dass mein VC2005-Compiler irgendwie die Befehle falsch umsetzt. Daher wollte ich versuchen die Ungenauigkeit zu umgehen, in dem ich direkt die Subtraktion mit Assembler hinschreibe.
Eigentlich handelt es sich dabei um long double-Variablen, wenn ich aber den c++-Befehl "sizeof" auf long double anwende erhalte ich 64 Bit, genauso wie bei double. Heißt das er unterscheidet nicht zwischen long double und double?Ich hab leider nur oberflächliche Assembler-Kenntnisse.
int a = 20; int b = 25; _asm { mov eax, a sub eax, b mov a, eax }
Damit habe ich schon eine Subtraktion hinbekommen, allerdings handelt es sich bei dem Integer ja um eine 32-Bit-Variable, die genau in ein Register passte.
Wie mach ich das denn dann mit double, bzw. long double wenn es da doch einen Unterschied gibt; deren Größe geht ja über eine Registergröße hinaus.
Muss man das aufteilen, oder wie kann man double / (long double) Variablen mit Assembler subtrahieren?
(Ein Codebeispiel wäre echt nett)Vielen Dank für Hilfe und viele Grüße
Andreas
-
floatingpoint-arithmetik mit general purpose register der cpu ist zwar möglich, aber ineffizient. du solltest dementsprechend die register und instruktionen der fpu verwenden. also z.b.:
mov st, a mov st(1), b fsub st, st(1) ; a = a - b mov a, st
die fpu register sind 64bit breit. long double ist so definiert, dass es nicht weniger breit sein darf als double. abhängig vom compiler sind sie also im ungünstigsten falle gleich groß.
-
Hi,
erstmal vielen Dank für die Antwort!!!Ich habs jetzt so für ein Beispiel eingebaut:
#include "stdafx.h" #include <iostream> #include <fstream> int _tmain(int argc, _TCHAR* argv[]) { double a = 20; double b = 25; _asm { mov st, a mov st(1), b fsub st, st(1) ; a = a - b mov a, st } printf("Die Zahl lautet: %.5f", a); return 0; }
Leider kommt dann aber immer der Compilerfehler:
C:\dokumente und einstellungen\andy\eigene dateien\visual studio 2005\projects\testprojekt\testprojekt\testprojekt.cpp(41) : error C2404: 'ST': unzulässiges Register in 'Erster Operand'
Ich muss zugeben ich habe noch nie inline-Assembler verwendet, muss ich da noch etwas hinzufügen, damit er die Register der fpu erkennt?
Viele Grüße
Andreas
-
Guck mal nach FLD.
-
Und FST.
-
yup. war zu schnell geschossen, mein fehler
du musst den inhalt der variablen mit fld in auf den registerstapel kopieren. mit fst holst du dann das ergebnis von fsub wieder herunter.
fld a fld b fsub fst a
fsub ohne argumente subtrahiert st von st(1) und speichert das ergebnis in st.
-
Hallo vielen Dank für die Antworten,
der Compiler meckert auch nicht mehrIch hab den Code jetzt in das aufwändige Projekt eingebaut:
long double WertT =m_sTyp->Kosten_Sanierung*fTime2/10.0; long double dummy6 = 500000.7328123456798187; //dummy6-WertT _asm { ;fld WertT ;fsubr dummy6 ;fstp dummy6 fld dummy6 fld WertT fsub fst dummy6 }
Dann hab ich das ganze mit dem Debugger getestet und mir die Zahlen vor und nach der Assemblerausführung ausgeben lassen:
WertT 0.15827682614326477 double
dummy6 500000.73281234567 double
fTime2 0.052758939564228058 double
Kosten_Sanierung 30 intWertT 0.15827682614326477 double
dummy6 500000.56250000000 double
fTime2 0.052758939564228058 double
Kosten_Sanierung 30 intLeider sieht man auch hier wieder, dass er ziemlich ungenau gerechnet hat. Gibts noch andere Befehle, die ihn dazu veranlassen genauer zu rechnen, oder was kann man gegen diese Ungenauigkeit tun?
Ich kann diese Ungenauigkeit weder in C++ nich in Assembler nachvollziehen, woran kann das liegen?
Viele Grüße
Andreas
-
bei all diesen fragen hilft dies bestimmt weiter
:
-
Hallo,
ich muss zugeben dass ich da nicht allzuviel verstanden habe
Da steht aber doch auch "windows has _controlfp() but it takes different parameters", oder hab ich da was falsch verstanden?Zielt das nicht insgesamt darauf ab, was ich auch mit der Compiler-Einstellung Strict (/fp:strict) statt Precise (/fp:precise) erreiche.
Zumindes hab ich diese Einstellung ausprobiert und die hat auch nichts gebracht.Ist trotzdem _controlfp() mit mir unbekannten Parametern die Lösung für das Problem?
Viele Grüße
Andreas
-
Hallo, erstmal vielen Dank für die ganzen Antworten,
ich hab den Fehler jetzt endlich gefundenDirectX hat mir die Genauigkeit des FPU herabgesetzt, ich hätte das Flag D3DCREATE_FPU_PRESERVE mitangeben müssen, damit dieses nicht passiert.
Viele Grüße
Andreas