 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Lars Martin Guest
|
Posted: Fri Dec 10, 2004 8:53 am Post subject: Gleiche Funktion in zwei Programmen führt zu unterschiedlich |
|
|
Hallo,
ich habe hier ein Problem wo ich inzwischen nicht mehr weiß wie ich
weiter komme. Das ganze ist unter Windows XP und BorlandC++ 5
programmiert.
Es gibt zwei Programme, eins mit einer grafischen Oberläche (im
folgenden mal gui genannt) und eine Konsolenanwendung. Beide Programme
linken statisch eine kern.dll beim Linken hinzu. Alle wichtigen
Funktionen stehen in der Kern.dll. Während der Laufzeit ruft die
kern.dll Funktionen aus einer weiteren dynamisch geladenen DLL auf
(nennen wir sie mal modell.dll).
Eine Funktion in der modell.dll berechnet sich sowas wie ein Minimum
aus einer Liste von werten ( Die eigentliche Funktion ist am ende,
hier nur die Kurzform und auf die Datentypen reduziert) :
unsigned int a[5];
unsigned int b[5];
double quote = 10000.0;
int ergebnis = 0;
for (int i = 1; i <= 4; i++) {
if( (((double)a[i]) / b[i]) < quote) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
Angenommen in a stehen folgende Werte: {0,60,1,1,1} und in b :
{0,60,20,20,20}
Und nun zu dem Problem:
Die Berechnung in der GUI-Anwendung kommt zu dem Ergebnis ergebnis=2.
Ist meiner Meinung ja auch richtig. Bei
i=1 ist die Abfrage (1<1000) richtig also quote = 1 und ergebnis=1
i=2 (0.05<1) richtig also quote = 0.05 und ergebnis=2
i=3 (0.05<0.05) falsch
i=4 (0.05<0.05) falsch
Wenn die gleiche dll mit der Konsolenanwendung gestartet wird, kommt
als Ergebnis ergebnis=4 raus. Durch Ausschrieb habe ich
festgestellt,dass wohl folgendes passiert:
i=1 ist die Abfrage (1<1000) richtig also quote = 1 und ergebnis=1
i=2 (0.05<1) richtig also quote = 0.05 und ergebnis=2
i=3 (0.05<0.05) richtig also quote = 0.05 und
ergebnis=3
i=4 (0.05<0.05) richtig also quote = 0.05 und
ergebnis=4
Wieso zum Henker kommt das Programm auf die Idee 0.05 sei kleiner als
0.05.
Und vorallem ist das Ergebnis reproduzierbar, also immer wenn die
Funktion aus dem GUI-rogramm aufgerufen wird rechnet der Computer
richtig, immer wenn aus der Konsolenanwendung aufgerufen rechnet er
falsch.
Und um alles noch ein etwas komplizierter zu machen. Wenn ich die
Division in der Abfrage so schreibe:
double berechnete quote;
for (int i = 1; i <= 4; i++) {
berechnetequote = ((double)a[i]) / b[i];
if( berechnetequote < quote;) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
Kommen beide Programme auf das richtige Ergebnis. Ich verstehe
inzwischen die Welt nicht mehr, was geht hier nur schief.
Ich habe ja schon an Rundungsfehler gedacht oder daran, dass 0.05
nicht "genau" in einer double gespeichert werden kann, aber wieso
hängt das Ergebnis davon ab aus welcher Anwendung ich die Funktion
aufrufe?
Wenn jemand mir hier weiterhelfen kann könnte ich endlich wieder ruhig
schlafen ;-)
Gruß Lars
Und hier nun der "richtige" Quelltext:
typSegment* findeSegment(typSegment* aktSeg) {
BstRegalData* zRegalverwalter;
bool nochplatz;
int schritt = 0;
do {
zRegalverwalter = (BstRegalData*)
BstUserData(aktSeg->RegalVerwalter);
if ((int)zRegalverwalter->AnzLeerPaletten() <
(zRegalverwalter->maxLeerPaletten +
(schritt*zRegalverwalter->schrittLeerPaletten))) {
return aktSeg;
}
else {
double quote;
nochplatz = false;
quote = 1000.0;
typSegment* zielSeg = NULL;
typSegment* zlaufSeg = Seg1;
for (int i = 1; i <= 4; i++) {
zRegalverwalter = (BstRegalData*)
BstUserData(zlaufSeg->RegalVerwalter);
if (((zRegalverwalter->maxLeerPaletten +
(schritt*zRegalverwalter->schrittLeerPaletten))
<= (int)Kapazitaet(zlaufSeg->RegalVerwalter))) {
nochplatz = true;
// Das Segment suchen das das beste Verhältnis zwischen
Anzahl leerer Paletten und maxLeerPaletten+schrittweite hat
if ((int)zRegalverwalter->AnzLeerPaletten() <
(zRegalverwalter->maxLeerPaletten+(schritt*zRegalverwalter->schrittLeerPaletten))
&&
((((double)zRegalverwalter->AnzLeerPaletten()) /
(zRegalverwalter->maxLeerPaletten +
(schritt*zRegalverwalter->schrittLeerPaletten))) < quote)) {
quote = ((double)zRegalverwalter->AnzLeerPaletten()
/ (zRegalverwalter->maxLeerPaletten +
(schritt*zRegalverwalter->schrittLeerPaletten)));
zielSeg = zlaufSeg;
}
zlaufSeg = zlaufSeg->oberesSeg;
}
}
if (zielSeg){
return zielSeg;
}
}
schritt++;
} while (nochplatz);
return NULL;
}
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Fri Dec 10, 2004 1:01 pm Post subject: Re: Gleiche Funktion in zwei Programmen führt zuunterschiedl |
|
|
Lars Martin wrote:
| Quote: |
Und um alles noch ein etwas komplizierter zu machen. Wenn ich die
Division in der Abfrage so schreibe:
double berechnete quote;
for (int i = 1; i <= 4; i++) {
berechnetequote = ((double)a[i]) / b[i];
if( berechnetequote < quote;) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
Kommen beide Programme auf das richtige Ergebnis. Ich verstehe
inzwischen die Welt nicht mehr, was geht hier nur schief.
Ich habe ja schon an Rundungsfehler gedacht oder daran, dass 0.05
nicht "genau" in einer double gespeichert werden kann, aber wieso
hängt das Ergebnis davon ab aus welcher Anwendung ich die Funktion
aufrufe?
|
Es koennte sein, das die Anwendungen den Floating Point Coprozessor
etwas unterschiedlich initialisieren.
Ansonsten wuesste ich keinen Grund warum ein und dieselbe Library
unterschiedliche Ergebnisse bei gleichem Input liefern sollte.
(Ich versteh das so, dass Du die Library *nicht* nachkompilierst,
ansonsten koennten die Compiler unterschiedliche Strategien zur
Haltung von Zwischenergebnissen einbauen. Bei Gleitkommezahlen
kann das durchaus einen Unterschied machen. Aber das hast Du
ja nicht gemacht, die eigentliche Berechnung ist nur einmal
kompiliert worden).
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Fri Dec 10, 2004 1:13 pm Post subject: Re: Gleiche Funktion in zwei Programmen führt zuunterschiedl |
|
|
Lars Martin wrote:
| Quote: |
Kommen beide Programme auf das richtige Ergebnis. Ich verstehe
inzwischen die Welt nicht mehr, was geht hier nur schief.
|
Grundregel Nummer eins:
Bei Gleitkommezahlen und Berechnungen mit diesen *immer* ein Epsilon
einplanen. Du musst grundsaetzlich immer davon ausgehen, dass die
Berechnung irgendwo in der 14., 15. ... Stelle (oder auch
weiter vorne) Mist mitschleift, den Du bei allen Vergleichen einplanen
musst. D.h. aber auch, das ein Vergleich von Gleikommezahlen zb
auf Gleichheit grundsaetzlich verboten ist. Es ist lediglich
erlaubt nachzusehen, ob die Differenz der Zahlen so klein ist, dass
Du sie als gleich akzeptieren kannst. Selbiges fuer kleiner und groesser:
Damit eine Zahl A effektiv kleiner als eine Zahl B ist, muss A sich
zumindest um dieses ominoese Epsilon von B unterscheiden.
Wie gross Epsilon sein muss, haengt von Deiner Anwendung und der
Vorgeschichte der Zahl ab: Wo kommen sie her, welche Berechnungen
wurden durchgefuehrt, etc.
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Peter Schütte Guest
|
Posted: Fri Dec 10, 2004 1:32 pm Post subject: Re: Gleiche Funktion in zwei Programmen führt zu unterschie |
|
|
Karl Heinz Buchegger wrote:
| Quote: | Grundregel Nummer eins:
Bei Gleitkommezahlen und Berechnungen mit diesen *immer* ein Epsilon
einplanen.
|
C++ hat von C die entsprechenden Makros aus <limits.h> bzw. <climits>
übernommen, hier insbesondere FLT_EPSILON bzw. DBL_EPSILON, die einen
Wert angeben für den gilt:
1.0 + epsilon != 1.0
Gruß Peter
--
Old beliefs do not lead you to new cheese.
[Who Moved My Cheese?, Spencer Johnson]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Horst Kraemer Guest
|
Posted: Fri Dec 10, 2004 7:53 pm Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
[email]lars.martin (AT) imail (DOT) de[/email] (Lars Martin) wrote:
| Quote: | Hallo,
ich habe hier ein Problem wo ich inzwischen nicht mehr weiß wie ich
weiter komme. Das ganze ist unter Windows XP und BorlandC++ 5
programmiert.
Es gibt zwei Programme, eins mit einer grafischen Oberläche (im
folgenden mal gui genannt) und eine Konsolenanwendung. Beide Programme
linken statisch eine kern.dll beim Linken hinzu. Alle wichtigen
Funktionen stehen in der Kern.dll. Während der Laufzeit ruft die
kern.dll Funktionen aus einer weiteren dynamisch geladenen DLL auf
(nennen wir sie mal modell.dll).
Eine Funktion in der modell.dll berechnet sich sowas wie ein Minimum
aus einer Liste von werten ( Die eigentliche Funktion ist am ende,
hier nur die Kurzform und auf die Datentypen reduziert) :
unsigned int a[5];
unsigned int b[5];
double quote = 10000.0;
int ergebnis = 0;
for (int i = 1; i <= 4; i++) {
if( (((double)a[i]) / b[i]) < quote) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
|
Das erste Minimum von Quotienten ganzer Zahlen >0 sucht man so:
unsigned long qa = INT_MAX, qb = 1;
for (int i = 1; i <= 4; i++)
if( (a[i]*qb < b[i]*qa) {
ergebnis = i; qa = a[i] ; qb = b[i];
}
Das funktioniert auf allen Rechnerarchitekturen, die ganze Zahlen
koennen, mathematisch exakt - vorausgesetzt, die Produkte liegen im
Bereich von unsigned long.
--
Horst
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Fri Dec 10, 2004 10:54 pm Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
"Lars Martin" <lars.martin (AT) imail (DOT) de> schrieb im Newsbeitrag
news:64f8143c.0412100053.1f5c34dc (AT) posting (DOT) google.com...
| Quote: | Hallo,
ich habe hier ein Problem wo ich inzwischen nicht mehr weiß wie ich
weiter komme. Das ganze ist unter Windows XP und BorlandC++ 5
programmiert.
Es gibt zwei Programme, eins mit einer grafischen Oberläche (im
folgenden mal gui genannt) und eine Konsolenanwendung. Beide Programme
linken statisch eine kern.dll beim Linken hinzu.
|
[snip]
| Quote: | Und vorallem ist das Ergebnis reproduzierbar, also immer wenn die
Funktion aus dem GUI-rogramm aufgerufen wird rechnet der Computer
richtig, immer wenn aus der Konsolenanwendung aufgerufen rechnet er
falsch.
|
Generelle Frage: Das GUI-Programm wird über die IDE kompiliert, oder?
Und das Konsolenprogramm? Auch über die IDE, oder über die Kommandozeile?
( Ich habe beim Borland 5.5.1 da mal meine Wunder erlebt, weil offenbar die
Optioneneinstellung in der IDE einen bug hatten.)
Und über was wurde die DLL erstellt?
Sind alle sonstigen Einstellungen identisch (Laufzeit-Packages,
Bibliotheken, Fließkommaeinstellungen...)?
| Quote: |
Und um alles noch ein etwas komplizierter zu machen. Wenn ich die
Division in der Abfrage so schreibe:
double berechnete quote;
for (int i = 1; i <= 4; i++) {
berechnetequote = ((double)a[i]) / b[i];
if( berechnetequote < quote;) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
Kommen beide Programme auf das richtige Ergebnis. Ich verstehe
inzwischen die Welt nicht mehr, was geht hier nur schief.
Ich habe ja schon an Rundungsfehler gedacht oder daran, dass 0.05
nicht "genau" in einer double gespeichert werden kann, aber wieso
hängt das Ergebnis davon ab aus welcher Anwendung ich die Funktion
aufrufe?
|
OK, nur daß ich das richtig verstehe: Wird die Funktion jetzt jeweils neu
mitkompiliert oder nicht? Bzw. unter welchen genauen Einstellungen (wieder
Bibliotheken, Fließkommapräzision, register-Variablen..) wurde die DLL
erstellt?
In Deinem Codebsp. könnte die Genauigkeit zwischen memory und Registern eine
Rolle spielen.
Hast Du den assembler-Code angeschaut?
Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Marcel Müller Guest
|
Posted: Sat Dec 11, 2004 11:16 pm Post subject: Re: Gleiche Funktion in zwei Programmen führt zu unterschie |
|
|
Peter Schütte wrote:
| Quote: | C++ hat von C die entsprechenden Makros aus <limits.h> bzw. <climits
übernommen, hier insbesondere FLT_EPSILON bzw. DBL_EPSILON, die einen
Wert angeben für den gilt:
1.0 + epsilon != 1.0
|
Diese sind in diesem Kontext in keiner Weise hilfreich. Sie stellen das
LSB der Floats dar. Das sagt aber nichts über die typischen Abweichungen
nach mehr als einer Rechenoperation aus.
Wer Programme schreibt, bei denen Floatingpointzahen mit == verglichen
werden, oder bei denen es auf den unterschied zwischen >= und > ankommt,
hat in 99% aller Fälle einen Designfehler im Konzept. Das hindert
freilich niemanden daran, es immer und immer wieder zu tun
(Fachliteratur eingeschlossen).
Der gezeigte Code fällt in eben diese Kategorie, da er nach einem
exakten Datentyp verlangt. In diesem Fall wäre ein "rational" Datentyp
der richtige. Float (und double) eignen sich definitiv nicht, auch wenn
man es im Einzelfall vielleicht hingebogen bekommt.
Eine Rational-Klasse ist gleich eine schöne C++ Aufgabe. Im Standard ist
meines Wissens keine inclusive.
Marcel
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Ralf Wiessner Guest
|
Posted: Sun Dec 12, 2004 12:44 am Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
[email]lars.martin (AT) imail (DOT) de[/email] (Lars Martin) schrieb:
| Quote: | unsigned int a[5];
unsigned int b[5];
double quote = 10000.0;
int ergebnis = 0;
for (int i = 1; i <= 4; i++) {
if( (((double)a[i]) / b[i]) < quote) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
|
Das casten in deiner if Abfrage ist etwas fragwürdig:
Du castes nur den a Vector nach double, machst dann eine
division, bei der der Compiler den b Vector implicite nach double
casten muss, danach der Vergleich mit einem double wert.
Zwei zeilen weiter unten im Code machst du das nochmal.
Sowas ist gefährlich, weil man dem Compiler zu viel Freiraum
gibt: Castet er nach double oder nicht?
besser ist (je nachdem, was du erreichen willst:
if ((double)a[i]/(double)b[i]) < quote) {...}
oder
if ((double)(a[i]/b[i]) < quote)
| Quote: | Angenommen in a stehen folgende Werte: {0,60,1,1,1} und in b :
{0,60,20,20,20}
Und nun zu dem Problem:
Die Berechnung in der GUI-Anwendung kommt zu dem Ergebnis ergebnis=2.
Ist meiner Meinung ja auch richtig. Bei
i=1 ist die Abfrage (1<1000) richtig also quote = 1 und ergebnis=1
i=2 (0.05<1) richtig also quote = 0.05 und ergebnis=2
i=3 (0.05<0.05) falsch
i=4 (0.05<0.05) falsch
Wenn die gleiche dll mit der Konsolenanwendung gestartet wird, kommt
als Ergebnis ergebnis=4 raus. Durch Ausschrieb habe ich
festgestellt,dass wohl folgendes passiert:
i=1 ist die Abfrage (1<1000) richtig also quote = 1 und ergebnis=1
i=2 (0.05<1) richtig also quote = 0.05 und ergebnis=2
i=3 (0.05<0.05) richtig also quote = 0.05 und
ergebnis=3
i=4 (0.05<0.05) richtig also quote = 0.05 und
ergebnis=4
|
Das sieht nach unterschiedlichen internen Rundungsfehlern aus,
ist in den anderen Mails ja schon beschrieben. U.U sind die
Compilerflags unterschiedlich gesetzt?
Mfg. RW
--
Ralf Wiessner, Berlin
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Sun Dec 12, 2004 1:36 pm Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
"Ralf Wiessner" <fng05 (AT) wieszner (DOT) de> schrieb im Newsbeitrag
news:le4nr0tpb8a044btqpbk2cvq3b53r4os70 (AT) 4ax (DOT) com...
| Quote: | lars.martin (AT) imail (DOT) de (Lars Martin) schrieb:
unsigned int a[5];
unsigned int b[5];
double quote = 10000.0;
int ergebnis = 0;
for (int i = 1; i <= 4; i++) {
if( (((double)a[i]) / b[i]) < quote) {
ergebnis = i;
quote = (((double)a[i]) / b[i]);
}
}
Das casten in deiner if Abfrage ist etwas fragwürdig:
Du castes nur den a Vector nach double, machst dann eine
division, bei der der Compiler den b Vector implicite nach double
casten muss, danach der Vergleich mit einem double wert.
Zwei zeilen weiter unten im Code machst du das nochmal.
Sowas ist gefährlich, weil man dem Compiler zu viel Freiraum
gibt: Castet er nach double oder nicht?
|
Wie Du in einem Satz oben bereits gesagt hast, findet eine implizite
Konvertierung nach double statt. Der cast nach double des b[i] Elementes
findet auf jeden Fall statt, kein Freiraum.
| Quote: |
besser ist (je nachdem, was du erreichen willst:
if ((double)a[i]/(double)b[i]) < quote) {...}
oder
if ((double)(a[i]/b[i]) < quote)
|
Oh je.
Das Problem hier ist daß die Division mit zwei unsigned int abläuft - der
cast dieses Ergebnisses ist zu spät, da das Kind dann schon im Brunnen
liegt. Außerdem ist er unnötig, da quote vom Typ double ist.
Generell würde ich einen static_cast
lesbarer ist (für mich zumindest). Ob man beide Argumente für operator/ so
castet, oder nur einen, ist lediglich Stilsache.
Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Lars Martin Guest
|
Posted: Mon Dec 13, 2004 8:01 am Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
Hallo Thomas,
"Thomas Mang" <nospam (AT) nospam (DOT) prima.de> schrieb im Newsbeitrag
news:41ba291e$0$10836$3b214f66 (AT) usenet (DOT) univie.ac.at...
| Quote: | Generelle Frage: Das GUI-Programm wird über die IDE kompiliert, oder?
Und das Konsolenprogramm? Auch über die IDE, oder über die Kommandozeile?
( Ich habe beim Borland 5.5.1 da mal meine Wunder erlebt, weil offenbar
die
Optioneneinstellung in der IDE einen bug hatten.)
Und über was wurde die DLL erstellt?
|
Beide Programme werden über ein Makefile erzeugt, über verschiedenen Targets
im Makefile. Alle Compilereinstellungen und Optionen sind die selben, einzig
die GUI-Anwendung wird mit -tWM (also Multithreaded) übersetzt, die Konsolen
Anwenung mit -tWC (also wahrscheinlich nicht als Multithreaded), mal schauen
was passiert, wenn ich beide als Singlethread Anwendung übersetze.
| Quote: | Sind alle sonstigen Einstellungen identisch (Laufzeit-Packages,
Bibliotheken, Fließkommaeinstellungen...)?
|
Ja, bis auf die oben beschriebene Sache.
| Quote: | OK, nur daß ich das richtig verstehe: Wird die Funktion jetzt jeweils neu
mitkompiliert oder nicht? Bzw. unter welchen genauen Einstellungen (wieder
Bibliotheken, Fließkommapräzision, register-Variablen..) wurde die DLL
erstellt?
|
Die DLL mit der Funktion wird nur einmal übersetzt, und anschließend von den
beiden Programmen dynamsich während der Laufzeit dazugeladen.
| Quote: | In Deinem Codebsp. könnte die Genauigkeit zwischen memory und Registern
eine
Rolle spielen.
In diese Richtung gehen unsere Vermutungen auch, nur ist mir nicht klar |
warum nicht bei beiden Anwenungen, die Ungenauigkeit auftritt sondern nur in
der einen. Soweit ich DLL's verstanden habe lege ich doch mit der Erstellung
der DLL alle Einstellungen und "Verhaltensweisen" fest. Und es dürfte
eigentlich egal sein was für eine Anwendung diese DLL aufruft.
Gruß
Lars
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Lars Martin Guest
|
Posted: Mon Dec 13, 2004 8:06 am Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
"Horst Kraemer" <h-kraemer (AT) lycos (DOT) de> schrieb im Newsbeitrag
news:15vjr0hc9vqvhkmn4jgfd74p9mqg33ivs2 (AT) 4ax (DOT) com...
| Quote: | lars.martin (AT) imail (DOT) de (Lars Martin) wrote:
Das erste Minimum von Quotienten ganzer Zahlen >0 sucht man so:
unsigned long qa = INT_MAX, qb = 1;
for (int i = 1; i <= 4; i++)
if( (a[i]*qb < b[i]*qa) {
ergebnis = i; qa = a[i] ; qb = b[i];
}
Das funktioniert auf allen Rechnerarchitekturen, die ganze Zahlen
koennen, mathematisch exakt - vorausgesetzt, die Produkte liegen im
Bereich von unsigned long.
--
Horst
Ist wahrscheinlich die sicherste Art zwei double Werte miteinander zu |
vergleichen, obwohl die Sache für einen der sich den Quelltext anschaut
nicht gerade sofort erschliest was da gemacht wird .
Aber nach diesem blöden Fehler werd ich es in Zukunft so programmieren.
Vielen Dank,
Lars
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Mon Dec 13, 2004 10:46 am Post subject: Re: Gleiche Funktion in zwei Programmen führt zuunterschiedl |
|
|
Peter Schütte wrote:
| Quote: |
Karl Heinz Buchegger wrote:
Grundregel Nummer eins:
Bei Gleitkommezahlen und Berechnungen mit diesen *immer* ein Epsilon
einplanen.
C++ hat von C die entsprechenden Makros aus <limits.h> bzw.
übernommen, hier insbesondere FLT_EPSILON bzw. DBL_EPSILON, die einen
Wert angeben für den gilt:
1.0 + epsilon != 1.0
|
Richtig.
Nur ist dieser Wert in der Praxis, um es mal freundlich
auszudruecken, fuer die Katz.
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Horst Kraemer Guest
|
Posted: Mon Dec 13, 2004 6:42 pm Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ |
|
|
"Lars Martin" <lars.martin (AT) imail (DOT) de> wrote:
| Quote: |
"Horst Kraemer" <h-kraemer (AT) lycos (DOT) de> schrieb im Newsbeitrag
news:15vjr0hc9vqvhkmn4jgfd74p9mqg33ivs2 (AT) 4ax (DOT) com...
[email]lars.martin (AT) imail (DOT) de[/email] (Lars Martin) wrote:
Das erste Minimum von Quotienten ganzer Zahlen >0 sucht man so:
unsigned long qa = INT_MAX, qb = 1;
for (int i = 1; i <= 4; i++)
if( (a[i]*qb < b[i]*qa) {
ergebnis = i; qa = a[i] ; qb = b[i];
}
Das funktioniert auf allen Rechnerarchitekturen, die ganze Zahlen
koennen, mathematisch exakt - vorausgesetzt, die Produkte liegen im
Bereich von unsigned long.
--
Horst
Ist wahrscheinlich die sicherste Art zwei double Werte miteinander zu
vergleichen, obwohl die Sache für einen der sich den Quelltext anschaut
nicht gerade sofort erschliest was da gemacht wird .
Aber nach diesem blöden Fehler werd ich es in Zukunft so programmieren.
Vielen Dank,
|
Das Problem ist Dir nur durch die Diskrepanz aufgestossen, fuer die
ich aus dem hohlen Bauch auch keine richtige Erklaerung habe, aber es
ist ein Programmierfehler prinzipieller Natur. Dieses Programm gibt
sozusagen "standardmaessig" 0 (falsch) aus (bei mir compiliert mit
Borland C++ 5.5.1)
#include
int main()
{
unsigned u2=2,u3=3;
double d;
d = (double)u2/u3;
printf("%dn", d == (double)u2/u3);
return 0;
}
Der Grund ist, dass die Werte (double)u2 und (double)u3 implizit vor
der Multiplikation in long double konvertiert werden und das Ergebnis
des Ausdrucks (double)u2/(double)u3 zwar C-semantisch 'double' ist,
aber "physisch" long double. Bei der Zuweisung an d wird der long
double, der im Copro bereitsteht, in double konvertiert, aber beim
Vergleich
d == (double)u2/u3;
wird in Wirklichkeit
(long double)d == (long double)2/(long double)3
berechnet, was deshalb in die Hose geht, weil links
(long double)(double)((long double)2/(long double)3)
und rechts
(long double)2/(long double)3
steht. D.h. die Zwischenkonvertierung des long double-Wertes nach
double durch das Speichern in d und das Zurueckkonvertieren liefert
einen anderen Wert als die direkte Multiplikation, weil das
Divisionsergebnis noch Stellen "hinter" den double-Stellen hat.
Der Compiler darf so etwas nach Standard machen, d.h. er darf mit
hoeherer Genauigkeit rechnen als vom C++-Ausdruck festgelegt.
Daher ist es immer gefaerlich anzunehmen, dass berechnete Werte exakt
mit gespeicherten Werten uebereinstimmen, auch wenn der gespeicherte
Wert genau mit demselben Ausdruck gefuettert worden ist - siehe oben.
--
Horst
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|