mathematisches (?) Problem
-
Hallo, ich hab' ein merkwürdiges Problem mit dem BCB 5, bin nicht sicher ob es etwas mit dem Cast zu tun hat.
double zahl = log(64)/log(2)+1; // zahl = 7 double zahl2 = (zahl-4)*2; // zahl2 = 6 int zahl3 = zahl2; // zahl3 = 5 ShowMessage (zahl3);warum ist zahl3 = 5? in zahl2 steht doch eigentlich eine Ganzzahl, die man einem Integer zuweisen können müsste?
-
zahl2 ist wahrscheinlich ein, zwei Mü kleiner!
5.999999999999...
-
dieses bietet:
int main(){ unsigned double zahl = log(64)/log(2)+1; // zahl = 6 printf("%d\n", zahl); unsigned double zahl2 = (zahl-4)*2; // zahl2 = 4 printf("%d\n", zahl2); int zahl3 = zahl2; // zahl3 = 4 printf("%d\n", zahl3); }aber nur in der unsigned variante, ansonsten landest du im minus bereich
ps: ich hab extra mal geschaut, was %d, also dezimal da bringt.. log ist zu ungenau.
-
Also grundsätzlich erstmal:
Das Ergebnis müsste natürlich 6 sein, man kann das ja mal Schritt für Schritt ausrechnen (es kommen nur ganzzahlige Ergebnisse dabei raus). Es darf mathematisch nicht sein, dass das Ergebnis um ein Mü kleiner ist. Es ist ja auch bis zu der Stelle richtig, an der nach int gecastet wird (den int brauche ich für einen Array-Zugriff).Der Taschenrechner und Dev-Cpp liefern auch das richtige Ergebnis, nur der BCB verrechnet sich (übrigens auch nur beim log-Wert von 64, bei allen anderen funktioniert es).
-
Dieses Problem ist C / C++ spezifisch es gibt einfach bestimmte Nachkommawerte, die sich in Fließkommadatentypen nicht abbilden lassen. Welche Werte das sind, ist Datentypabhängig.
Das war schon immer so und wird immer so sein. Deswegen: Zum Schätzen nimmt man Fließkommadatentypen, zum Rechnen Intergerdatentypen.
-
Joe_M. schrieb:
Dieses Problem ist C / C++ spezifisch es gibt einfach bestimmte Nachkommawerte, die sich in Fließkommadatentypen nicht abbilden lassen. Welche Werte das sind, ist Datentypabhängig.
Das war schon immer so und wird immer so sein. Deswegen: Zum Schätzen nimmt man Fließkommadatentypen, zum Rechnen Intergerdatentypen.Es ist natürlich klar, dass beim Umwandeln von Typen Datenverlust entsteht, in diesem Fall ist es aber unlogisch, weil an keiner Stelle im Code (als Ergebnis) eine wirkliche Fließkommazahl entsteht (log(64)/log(2) = 6, +1 = 7, -4 = 3, *2 = 6). Wo soll da die 5 herkommen?
Naja, ist ja auch egal, kann mir vielleicht jemand einen Tipp geben, wie bei der Rechnung auch wirklich 6 rauskommt?
-
wenn du einen integralen datentyp erwartest, solltest du das ergebnis runden und dann zuweisen.
#define MF_LN_2 0.69314718055994530941723212145818 // log(2) (nat. Log.) //--------------------------------------------------------------------------- // Funktion liefert dualen Logarithmus von 'x' (Basis 2) //--------------------------------------------------------------------------- inline double Log2(const double &x) { return (log(x) / MF_LN_2); } //--------------------------------------------------------------------------- // Funktion rundet die angegebene Gleitkommazahl auf die nächste // Ganzzahl (integer) auf oder ab. //--------------------------------------------------------------------------- inline int Round(const double &x) { return ((int) (x < 0 ? (x - 0.5) : (x + 0.5))); }double v1 = Log2(64); // v = 6 int v2 = Round(Log2(64)); // v = 6
-
Joe_M. schrieb:
Dieses Problem ist C / C++ spezifisch
Nein, das Problem ist nicht C/C++ spezifisch, dasselbe Problem hat man auch bei Delphi, VB o.ä.
Das liegt an der internen Darstellung von Fließkommazahlen und so ziemlich jeder Programmierer
(mich eingeschlossen) ist damit wohl schon mal auf die Schnauze gefallen.Man muss halt bei der Verwendung von Fließkommazahlen immer daran denken, dass die Genauigkeit
beschränkt ist. Bitweises Vergleichen ist kritisch und die Umwandlung in Ganzzahlen offensichtlich
auch.Wie Altenburger schon angemerkt hat ist der Ganzzahlwert der berechneten Fließkommazahl wohl 5 und
der Rest wird beim Cast einfach abgeschnitten.Gruß,
Alexander
-
elise schrieb:
unsigned double zahl = log(64)/log(2)+1; // zahl = 6seit wann gibts unsigned auch fuer gleitkommatypen? meines wissens gilt das nur bei ganzzahltypen (char, int, long, short, __int64).
-
Ok, ich hab' es inzwischen hinbekommen, danke.

Eines würde mich aber doch interessieren:
Wie Altenburger schon angemerkt hat ist der Ganzzahlwert der berechneten Fließkommazahl wohl 5 und
der Rest wird beim Cast einfach abgeschnitten.Wie kommt man da auf 5? Das Ergebnis ist genau 6.

log(64)/log(2) ist genau 6 und der Rest ist ja wohl auch klar! Ich verstehe nicht, wie da was verloren gehen kann, sogar mein Taschenrechner kommt auf das richtige Ergebnis.... ich hab' auch mal nachgerechnet (einzelne Werte von den Logarithmen). wenn man Nachkommastellen abschneidet müsste eigentlich ein Wert über 6 rauskommen.
-
Da hilft wohl nur, dass Du mal in die Welt der Fließkommazahlen (oder anscheinend besser Gleitkomma-
zahlen) einsteigst. Das lernt man beispielsweise in den Grundlagenvorlesungen im Informatikstudium.
Falls Du keine Lust hast Informatik zu studieren, kannst Du auch mal hier schauen.
Wenn Du dann immer noch nicht weißt, warum das Ergebnis nicht genau 6 ist, musst Du halt doch
Informatik studieren
Gruß,
Alexander