C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Gleiche Funktion in zwei Programmen führt zu unterschiedlich

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Lars Martin
Guest





PostPosted: Fri Dec 10, 2004 8:53 am    Post subject: Gleiche Funktion in zwei Programmen führt zu unterschiedlich Reply with 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]);
}
}

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





PostPosted: Fri Dec 10, 2004 1:01 pm    Post subject: Re: Gleiche Funktion in zwei Programmen führt zuunterschiedl Reply with quote



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





PostPosted: Fri Dec 10, 2004 1:13 pm    Post subject: Re: Gleiche Funktion in zwei Programmen führt zuunterschiedl Reply with quote



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





PostPosted: Fri Dec 10, 2004 1:32 pm    Post subject: Re: Gleiche Funktion in zwei Programmen führt zu unterschie Reply with quote

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





PostPosted: Fri Dec 10, 2004 7:53 pm    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote

[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





PostPosted: Fri Dec 10, 2004 10:54 pm    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote


"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





PostPosted: Sat Dec 11, 2004 11:16 pm    Post subject: Re: Gleiche Funktion in zwei Programmen führt zu unterschie Reply with quote

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





PostPosted: Sun Dec 12, 2004 12:44 am    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote

[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





PostPosted: Sun Dec 12, 2004 1:36 pm    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote


"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





PostPosted: Mon Dec 13, 2004 8:01 am    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote

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





PostPosted: Mon Dec 13, 2004 8:06 am    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote


"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 Wink.
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





PostPosted: Mon Dec 13, 2004 10:46 am    Post subject: Re: Gleiche Funktion in zwei Programmen führt zuunterschiedl Reply with quote

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





PostPosted: Mon Dec 13, 2004 6:42 pm    Post subject: ...nktion in zwei Programmen f374hrt zu untersch...^ Reply with quote

"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 Wink.
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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.