 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Michael Wielsch Guest
|
Posted: Mon Sep 15, 2003 11:35 pm Post subject: C++ verrechnet sich |
|
|
Hallo,
Bei der Logarithmus funktion von <cmath> sind Dinge im Spiel die ich nicht
verstehe.
int dez=128;
int bit=(int)(log((double)dez) / log((double)2));
Ergibt 6, obwohl mein Taschenrechner eine 7 prophezeit. Auch mit einem
static_cast<int> ist das Ergebnis falsch. Wenn man für "dez" etwa 256 oder
512 oder sonst irgenteine Zahl über 128 einsetzt stimmt das ergebnis
wieder.
Und diese Version...
double bit=(log((double)dez) / log((double)2));
....ergibt nun eine schöne, glatte 7. Das spielchen lässt sich auch mit
log10(double) statt log(double) wiederhohlen.
Könnte es sein das mein GCC diesen Fehler produziert?
Leider fehlen mir die vergleichsmöglichkeiten.
Gruß
Michael
--
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 |
|
 |
Stefan Ring Guest
|
Posted: Tue Sep 16, 2003 8:55 am Post subject: Re: C++ verrechnet sich |
|
|
Irgendwie schade, dass durch all diese komplizierten Varianten der
Compiler nie die Möglichkeit hat, die wunderbaren i386 Bit Scan
Instruktionen zu benutzen. Die tun nämlich genau das.
--
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 |
|
 |
Dirk Clemens Guest
|
Posted: Tue Sep 16, 2003 3:35 pm Post subject: Re: C++ verrechnet sich |
|
|
Michael Wielsch wrote:
| Quote: | Hallo,
Bei der Logarithmus funktion von <cmath> sind Dinge im Spiel die ich nicht
verstehe.
int dez=128;
int bit=(int)(log((double)dez) / log((double)2));
|
Wie wärs mit Rundung:
in bit = floor ( log(dez) / log(2) + 0.5 );
Lemmi
--
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 |
|
 |
Markus Schaaf Guest
|
Posted: Tue Sep 16, 2003 4:30 pm Post subject: Re: C++ verrechnet sich |
|
|
"Stefan Ring" <e9725446 (AT) stud3 (DOT) tuwien.ac.at> schrieb:
| Quote: | Irgendwie schade, dass durch all diese komplizierten Varianten der
Compiler nie die Möglichkeit hat, die wunderbaren i386 Bit Scan
Instruktionen zu benutzen. Die tun nämlich genau das.
|
Und, Vorschläge? Am nähesten dran wäre wohl ein »ilogb« (welches
es in C99 gibt, aber nur für Gleitkommazahlen), das man in C++
für Ganzzahltypen überladen könnte. In C++98 verspricht »frexp«
wohl den meisten Erfolg, wenngleich ich mir nicht vorstellen kann,
daß es wirklich einen Compiler gibt, der das so optimiert (falls
man den Rückgabewert von »frexp« ignoriert, selbstverständlich).
Allerdings sollte selbst das normale »frexp« für modernere
Prozessoren mit FPU effizienter sein, als alle bisher geposteten
Varianten.
MfG
--
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 |
|
 |
Michael Wielsch Guest
|
Posted: Wed Sep 17, 2003 12:22 pm Post subject: Re: C++ verrechnet sich |
|
|
Stefan Ram wrote:
| Quote: | int main(){ ::std::cout
( ::std::log( 128. )
/
::std::log( 2. ))
- 7. << 'n'; }
|
Sehr interessant.
Das erklährt das Ergebnis des Taschenrechners und auch der
(int)(log()/log()) Version.
Aber an was liegt es das in manchen Fällen eine 7 das Ergebnis ist.
Kann std::cout nicht richtig mit double Zahlen umgehen? Zumindest ab der
15.ten Stelle.
--
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: Wed Sep 17, 2003 1:56 pm Post subject: Re: C++ verrechnet sich |
|
|
Michael Wielsch wrote:
| Quote: |
Stefan Ram wrote:
int main(){ ::std::cout
( ::std::log( 128. )
/
::std::log( 2. ))
- 7. << 'n'; }
Sehr interessant.
Das erklährt das Ergebnis des Taschenrechners und auch der
(int)(log()/log()) Version.
Aber an was liegt es das in manchen Fällen eine 7 das Ergebnis ist.
|
Das liegt daran, das Gleitkommazahlen in einem Computer and Kommezahlen wie
Du sie aus der Mathematik kennst, nun mal sehr wenig miteinander zu tun haben.
Auch wenn es fuer viele schwer zu akzeptieren ist: Ein Computer kann in den
meisten Faellen nun mal mit Gleitkommazahlen nicht exakt rechnen (zumindest
nicht so wie Du es aus der Mathematik erwarten wuerdest)
| Quote: | Kann std::cout nicht richtig mit double Zahlen umgehen? Zumindest ab der
15.ten Stelle.
|
Das hat nichts mit cout zu tun. Es ist vielmehr eine grundaetzliche Eigenschaft
einer Gleitkommaimplementierung. Der Mathematiker Cantor hat bewiesen, dass
es nun mal unendlich viele Zahlen zwischen 0.0 und 1.0 gibt. Wie soll man
aber unendlich viele Zahlen in nur 8 Byte (oder was auch immer) unterbringen?
Es geht nicht. Also muss man mit Naeherungen operieren. Dein Rechenergebniss
ist nun halt nicht exact 7.0, sondern in manchen Faellen vielleicht 6.9999999999998
oder 7.00000000000001. Also eine Zahl die sehr nahe an 7 liegt aber eben nicht
genau 7 ist. Dein Taschenrechner weiss das auch und berechnet seine Ergebnisse
mit mehr Kommastellen als er dir anzeigt. Bevor er Dir das Ergebnis praesentiert,
*rundet* er es auf die anzuzeigenden Kommastellen. cout (genauer der operator<<
fuer double) tut das auch, und so wird aus 6.999999999999998 bei 6 anzuzeigenden
Nachkommastellen wieder 7. Nur wenn Du explizit sagst: schneide die Nachkommastellen
ab, dann wird aus 6.99999999999999998 eben 6.
--
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 |
|
 |
Uwe Schnitker Guest
|
Posted: Thu Sep 18, 2003 6:08 am Post subject: Re: C++ verrechnet sich |
|
|
Karl Heinz Buchegger <kbuchegg (AT) gascad (DOT) at> wrote
| Quote: | Michael Wielsch wrote:
Stefan Ram wrote:
int main(){ ::std::cout
( ::std::log( 128. )
/
::std::log( 2. ))
- 7. << 'n'; }
Sehr interessant.
Das erklährt das Ergebnis des Taschenrechners und auch der
(int)(log()/log()) Version.
Aber an was liegt es das in manchen Fällen eine 7 das Ergebnis ist.
Das liegt daran, das Gleitkommazahlen in einem Computer and Kommezahlen wie
Du sie aus der Mathematik kennst, nun mal sehr wenig miteinander zu tun haben.
Auch wenn es fuer viele schwer zu akzeptieren ist: Ein Computer kann in den
meisten Faellen nun mal mit Gleitkommazahlen nicht exakt rechnen (zumindest
nicht so wie Du es aus der Mathematik erwarten wuerdest)
Kann std::cout nicht richtig mit double Zahlen umgehen? Zumindest ab der
15.ten Stelle.
Das hat nichts mit cout zu tun. Es ist vielmehr eine grundaetzliche
Eigenschaft
einer Gleitkommaimplementierung. Der Mathematiker Cantor hat bewiesen, dass
es nun mal unendlich viele Zahlen zwischen 0.0 und 1.0 gibt.
|
Sorry, aber das wusste man schon sehr viel eher. Was Cantor bewiesen hat,
ist dass es überabzählbar viele relle Zahlen zwischen 0 und 1 gibt. Der
Unterschied zwischen abzählbar unendlich und überabzählbar unendlich ist
aber für die Implementierung von Gleitkommaarithmetik irrelevant.
| Quote: | Wie soll man
aber unendlich viele Zahlen in nur 8 Byte (oder was auch immer) unterbringen?
|
In der Praxis wird ein Programm immer nur endlich viele Variablen verwenden.
Es reicht also, wenn man es schafft, eine beliebige endliche Auswahl aus den
überabzählbar vielen Möglichen darzustellen.
Hmm - nachdenk, grübel - könnte man nicht die Basis der Exponentialdarstellung
variabel machen? Ein "suprafloat" besteht aus Mantisse, Exponent und Basis?
Und bei jeder Berechnung wird, wenn nötig, versucht, die Basis anzupassen?
Wär mal lustig, sowas auszuprobieren.
| Quote: | Es geht nicht. Also muss man mit Naeherungen operieren.
|
Wer sagt das?
Wenn es unmöglich ist "unendlich viele Zahlen in nur 8 Byte unterbringen".
muss man sich auf endlich viele Zahlen beschränken. Oder? Oder man muss
unendlich viele Bytes zulassen.
Und da ein Programm immer nur endlich viele Werte tatsächlich benötigt,
kann man sowas machen. Das nennt man wohl "Arbitrary Precision Numbers"
oder so ähnlich, und Gerüchten zufolge sollen Banken und ähnliche
Institutionen, welche auf hohe Genauigkeit angewiesen sind, so was
ja auch machen. (Anderen Gerüchten zufolge sollen es aber gewisse
institutionen bei der Berechnung von Finanzdaten nicht immer so
ganz genau nehmen. Hmm. Man weiss es nicht, man steckt nicht drin.)
Sowas braucht natürlich in der Regel mehr Speicher und mehr Rechenzeit
als Gleitkommaarithmetik, die deshalb - trotz des Risikos - nicht
totzukriegen sein wird.
| Quote: | --
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
Uwe
--
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: Thu Sep 18, 2003 12:19 pm Post subject: Re: C++ verrechnet sich |
|
|
Uwe Schnitker wrote:
| Quote: |
Karl Heinz Buchegger <kbuchegg (AT) gascad (DOT) at> wrote
Das hat nichts mit cout zu tun. Es ist vielmehr eine grundaetzliche
Eigenschaft
einer Gleitkommaimplementierung. Der Mathematiker Cantor hat bewiesen, dass
es nun mal unendlich viele Zahlen zwischen 0.0 und 1.0 gibt.
Sorry, aber das wusste man schon sehr viel eher.
|
Aehm. Glaub ich Dir mal. Ich habe mich nie naeher mit der Geschichte befasst.
| Quote: | Was Cantor bewiesen hat,
ist dass es überabzählbar viele relle Zahlen zwischen 0 und 1 gibt.
|
Richtig das wars. Cantor's Diagonalargument.
| Quote: | Der
Unterschied zwischen abzählbar unendlich und überabzählbar unendlich ist
aber für die Implementierung von Gleitkommaarithmetik irrelevant.
|
Eben.
| Quote: |
Wie soll man
aber unendlich viele Zahlen in nur 8 Byte (oder was auch immer) unterbringen?
In der Praxis wird ein Programm immer nur endlich viele Variablen verwenden.
Es reicht also, wenn man es schafft, eine beliebige endliche Auswahl aus den
überabzählbar vielen Möglichen darzustellen.
Hmm - nachdenk, grübel - könnte man nicht die Basis der Exponentialdarstellung
variabel machen? Ein "suprafloat" besteht aus Mantisse, Exponent und Basis?
Und bei jeder Berechnung wird, wenn nötig, versucht, die Basis anzupassen?
Wär mal lustig, sowas auszuprobieren.
|
An die Performance wage ich nicht mal zu denken :-)
| Quote: |
Es geht nicht. Also muss man mit Naeherungen operieren.
Wer sagt das?
Wenn es unmöglich ist "unendlich viele Zahlen in nur 8 Byte unterbringen".
muss man sich auf endlich viele Zahlen beschränken. Oder?
|
Ich sehe hier nicht worauf Du hinaus willst. Wenn man sich auf endlich vielen
Zahlen einschraenken muss, muss zwangslauefig irgend etwas mit den Zahlen
geschehen, die nicht in dieser Menge enthalten sind. Die beste Loesung ist
dann ziemlich sicher eine Naehrung, obwohl das natuerlich nicht zwingend ist.
| Quote: | Oder man muss
unendlich viele Bytes zulassen.
Und da ein Programm immer nur endlich viele Werte tatsächlich benötigt,
kann man sowas machen. Das nennt man wohl "Arbitrary Precision Numbers"
oder so ähnlich, und Gerüchten zufolge sollen Banken und ähnliche
Institutionen, welche auf hohe Genauigkeit angewiesen sind, so was
ja auch machen. (Anderen Gerüchten zufolge sollen es aber gewisse
institutionen bei der Berechnung von Finanzdaten nicht immer so
ganz genau nehmen. Hmm. Man weiss es nicht, man steckt nicht drin.)
|
Ich bin zwar nicht aus der Bankbranche. Ich erinnere mich aber an
einen Ausspruch eines meiner Praktikumsleiter: "Wer fuer Geldwerte
Gleitkommaarithmetik nimmt, gehoert sowieso sofort an die Wand gestellt." :-)
--
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 |
|
 |
|
|
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
|
|