bei int maximal 46340 warum???
-
#include <iostream> using namespace std ; int main() { while(true) { int zahl ; // maximal 46340 warum??? cout << "Bitte geben Sie eine Zahl ein: "; cin >> zahl ; // Eingabe cout << "Quadratzahl: " << zahl * zahl << endl ; // Ausgabe } return 0 ; }
Kann mir jemand erklären warum beim Dev-Cpp Integer ab 46341 Blödsinn (d.h. negative Zahlen) liefert?
Bei (2^16)/2 wären das doch 32768?
-
Weil int 32 Bit hat, bzw. 31 Bit ohne Vorzeichen.
Die größte damit darstellbare Zahl ist 2147483647
Die Wurzel aus 2147483647 = 46340.9
D.h. alle Zahlen größer als 46340 im Quadrat führen zu einem Überlauf der int-Zahl, wodurch diese wieder im negativen Bereich von unten beginnt (der Überlauf in die höheren Bits geht verloren).
-
sehe nur, dass 32768 * 2^-(1/2) = 46341
Es ist also 2 ^ 16,5. Habe allerdings keine Ahnung warum. Da kann man nur staunen.
-
Hallo,
verstehe dein Problem nicht. int hat auf 32-Bit Systemen in der Regel 32-Bit.
Das macht einen Wertebereich von
[-2^31 = -2147483648 , (2^31) - 1 = 2147483647].Die zweite Wurzel aus (2^31) -1 ist ca. 46340.95.
Das Quadrat von 46341 ist damit also > (2^31) -1 und kann demzufolge nicht mehr korrekt in einem signed int dargestellt werden. In solchen Situationen kommt es in C++ zu einem Überlauf. D.h. addierst du auf (2^31) - 1 eins drauf, bist du wieder bei -2^31.
-
Oh mein Gott. *Viel* zu spät
-
Und so gehts dann doch:
#include <iostream> using namespace std; typedef long long i64; int main() { while(true) { i64 zahl; cout << "Bitte geben Sie eine Zahl ein: "; cin >> zahl ; // Eingabe cout << "Quadratzahl: " << zahl * zahl << endl ; // Ausgabe } }
Der Code sollte so mit gcc gehen. Mit MSVC müsste man einiges anders und auch umständlicher machen. Am einfachsten jedoch:
#include <iostream> using namespace std; int main() { while(true) { double zahl; cout << "Bitte geben Sie eine Zahl ein: "; cin >> zahl ; // Eingabe cout << "Quadratzahl: " << zahl * zahl << endl ; // Ausgabe } }
Geht überall.
-
Mr. N schrieb:
Und so gehts dann doch:
Der Code sollte so mit gcc gehen. Mit MSVC müsste man einiges anders und auch umständlicher machen. Am einfachsten jedoch:#include <iostream> using namespace std; int main() { while(true) { double zahl; cout << "Bitte geben Sie eine Zahl ein: "; cin >> zahl ; // Eingabe cout << "Quadratzahl: " << zahl * zahl << endl ; // Ausgabe } }
Geht überall.
Das stimmt nicht.
Du hast das ganze vielleicht unter Linux mit GCC und MSVC unter Windows auf einem i386 Rechner ausprobiert. Aber aus diesen Ergebnissen auf _ALLE_ Rechner + Betriebssystem Kombinationen zu schliessen ist falsch. Oder hast du das ganze auch auf einer AIX oder einer Cray ausprobiert? Und wie steht es mit irgendwelchen Embedded Geräten? Ist dort dein "double" gross genug?Wenn schon 32bit Integer nicht ausreichen, dann verwende "long long", das mit dem 99 final draft für C Einzug gehalten hat. Bei Microsoft gibt es noch den Microsoft-spezifischen Typ __int64, allerdings soll dieser Typ Buggy sein und lediglich wegen offset_t eingeführt worden sein.
-
Mr. N schrieb:
Und so gehts dann doch:
Die Lösung gefällt mir nicht wirklich, da sie das eigentliche Problem hier ignoriert. Du erweckst den Eindruck, daß man Überläufe alleine durch einen anderen Typ wegbekommt und daß dies ein banaler Fehler wäre.
Dabei wird er auch bei long long das gleiche Problem bekommen, nur wird die Zahl dann 3037000500 lauten, ab der das Ergebnis falsch wird.
Auch der Ausweg hin zu double hat seine Tücken, da man hier wegen der Stellenauslöschung am Ende in ganz neue Probleme rennt. Daß solche Grundlagen häufig falsch verstanden sind bemerkt man z.B. auch in diesem Thread http://www.c-plusplus.net/forum/viewtopic.php?t=43012
Jemand wie C++ Newbie sollte nämlich aus diesem Problem eine viel wichtigere Erkenntnis mitnehmen:
Computer können nicht rechnen.
Und das hat nichts mit Programmiersprachen oder Betriebssystemen zu tun.
-
Mr. N schrieb:
Mit MSVC müsste man einiges anders und auch umständlicher machen.
Wieso das?
Ein
typedef __int64 i64;
erfüllt für den MSVC den Zweck.
-
Marc++us schrieb:
Computer können nicht rechnen.
Und das hat nichts mit Programmiersprachen oder Betriebssystemen zu tun.
Lispdialekte oder Javas Bignum (oder so) rechnen beispielsweise erstaunlich richtig -- dafür, dass sie es eigentlich gar nicht können.
-
Wenn ich eine zusätzliche Lib brauche, nur damit ich genau rechnen kann, so bestätigt das meine Aussage doch nur.
Mit der vorsichtigen Variante "Computer können nicht rechnen" fährt man aber im Alltag wesentlich besser als mit einer "Computer sind Rechenmaschinen"-Naivität.
-
Marc++us schrieb:
Ein
typedef __int64 i64;
erfüllt für den MSVC den Zweck.
Leider nicht. Denn (zumindest in Version 6) implementiert der VC6 op>> und op<< nicht für __int64. IIRC
-
Marc++us schrieb:
Computer können nicht rechnen.
Korrekt. Genausowenig wie Menschen oder sonst irgendetwas existentes.
-
Ich verstehe Euch nicht.
Hier liegt ein Beitrag von einem Nutzer vor, der offensichtlich erstmalig mit Zahlenbereichen und Überläufen konfrontiert wird, und der auch nicht über tiefes Wissen in Assembler verfügt.
Statt hier eine Basis für das Verständnis für die Hintergründe der Rechnermathematik zu legen, höre ich Dinge wie "Javas Bignum" oder "auch Menschen können nicht rechnen, wozu die Aufregung mit den Computern".
Griffige Merkregeln passend zur Problematik - und diese auch zunächst mal erschöpfend behandelnd - werden zerredet mit Hinweisen auf deren Unvollständigkeit und deren Ausnahmen. Ist es denn so schwer, eine Aussage in einfache und verständliche Sätze zu packen, die dem Frager weiterhelfen? Trägt eine umfassende akademische Debatte wirklich etwas zum Verständnis des Fragers bei? Sind Zitate von IEEE- und ISO-Normen hilfreich, wenn ein Einsteiger ein typisches Problem hat? Und ist es nicht Zeichen von Verständnis, wenn man sein eigenes Wissen auf den Sprach- und Wissensbereichs des Fragers transformiert und dessen Problemkreis adaptiert, um das Problem verständlich zu erklären?
Ein Einsteiger stolpert im Laufe der Zeit über solche Probleme:
unsigned u = 1; while (u > 0) ++u;
Nach einfachem Verständnis ist das eine Endlosschleife. Es ist ein ganz wesentlicher Lernschritt wenn man versteht, daß diese Schleife trotzdem terminiert. Solche Erkenntnisse muß man doch unterstützen und nicht einfach umgehen.
--
Apropos: auf dem VC7 sind die Streamoperatoren auch für __int64 implementiert.
-
wie rechnen denn Taschenrechner, z.B. Windows' calc.exe? Welche einfache BigNum kann ich für Dev-Cpp verwenden? Oder soll ich auf C# umsteigen? Dort habe ich decimal gefunden, 128 bit.
-
@Marc++us: Bis vor diesem Post hast du selbst keine Anstalten gemacht, irgendetwas zu erklären. Aber egal. Du möchtest, dass die Tatsache der fixen Größe auf Computern erklärt wird? OK, es ist denke möglich das zu erklären. Aber es zu begründen ist wohl weniger einfach. Zumindest wenn die High-Level-Sicht der Dinge erhalten bleiben soll.
@c++ newbie: calc.exe ist in C++ geschrieben, da könnte ich fast mit dir wetten. Such mal mit google nach gmp. Bzw. lass es und kümmer dich um die Grundlagen *g*.
Du solltest dir klarmachen, dass ein Computer normalerweise (es lässt sich umständlich umgehen - das machen BigNum-Klassen) jede Zahl mit einer festen Anzahl Ziffern ansieht. Also beispielsweis 0210 statt 210 und 0004 statt 4. Logisch, dass dann Zahlen wie 10000 Probleme machen. Sie passen einfach nicht mehr rein. Dennoch wird die Zahl - wenn auch fehlerhaft - dargestellt als 0000. Das ist auch der Grund, weshalb Marc++us Schleife terminiert.
-
calc.exe nimmt wahrscheinlich long double. da ist aber gerinmge genauigkeit
-
warum koennen menschen nicht rechnen? wie ist in diesem zusammenhang rechnen definiert?
bugnum und 128bit haben so ziemlich gar nix miteinander zu tun.
-
PeterTheMaster schrieb:
warum koennen menschen nicht rechnen?
kannst du mit beliebigen zahlen rechnen? nein. es ist schlicht das problemchen mit der unendlichkeit.
-
Mr. N schrieb:
PeterTheMaster schrieb:
warum koennen menschen nicht rechnen?
kannst du mit beliebigen zahlen rechnen? nein. es ist schlicht das problemchen mit der unendlichkeit.
also ich kann. ich brauche dann nur unendlich viel zeit und genausoviel konzentration.
verstehe die diskussion an dieser stelle nicht.