[gelöst] Fortschrittsanzeige: Läuft Nur ruckweise im Linux-Terminal [vorher: Welcher Datentyp?]
-
Hallo,
für mein Programm möchte ich eine Fortschrittsanzeige.
Diese sieht erst einmal so aus:int fortschritt(long schr, long anz) { if ( schr%anz/25 == 0) { /* Fortschrittsanzeigen; absolut und prozentual */ cout << "Schritt " << schr << " von " << anz; cout << " ( " << schr*100/anz << " Prozent)" << endl; } return 0; }Nun habe ich festgestellt, dass ab einem bestimmten Wert für schr und anz die Prozentanzeige wieder "zurückspringt", z.B. von 40 auf 4.
Jetzt bin ich erstmal auf die Lösung umgestiegen, den Datentyp auf double zu ändern, und, damit die Modulo-Operation funktioniert, eine Typumwandlung durchzuführen:
int fortschritt(double schr, double anz) { if ( long (schr)%long (anz/25) == 0) { /* Fortschrittsanzeigen; absolutund prozentual */ cout << "Schritt " << schr << " von " << anz; cout << " ( " << schr*100/anz << " Prozent)" << endl; // "\r"; } return 0; }Dann treten leider "krumme" Werte (zB 32000001) für die Fortschrittsanzeige auf, was nicht unbedingt gewünscht ist.
Lange Rede, kurzer Sinn:
Kann ich das irgendwie eleganter lösen?(Die main() hab ich erstmal weggelassen, wenn sie benötigt wird, poste ich sie noch nach...)
Und bitte seid nachsichtig mit mir, ich hab erst seit 3 Monaten C++-Programmierung an der Schule (bei 2 Wochenstunden Informatik)

-
int fortschritt_in_prozent(int erledigt, int von) { return (erledigt * 100) / von; }
-
Auf die Idee, die Prozentanzeige nochmals auszulagern, bin ich nicht gekommen, danke für den Tipp.
Allerdings wird int als Datentyp nicht reichen...Aktueller Stand:
void fortschritt(long schr, long anz) { if ( schr%(anz/25) == 0) { /* Fortschrittsanzeigen; absolutund prozentual */ cout << "Schritt " << schr << " von " << anz; cout << " ( " << proz(schr, anz) << " Prozent)" << endl; } } double proz(double aktu, double gesa) { return aktu*100/gesa; }Allerdings bleibt das Problem mit zu großen Zahlen, wenn ich jetzt z.B. für schr 4924964562 übergebe, steht da plötzlich
Schritt 85899345 von -2147483648 ( -4 Prozent)
Aber long ist doch der größte Ganzzahltyp.
Natürlich könnte ich jetzt unsigned long nehmen, das würde den Berech verdoppeln. Allerdings geht es da auch irgendwann nicht weiter....Mit unsigned long sieht es so aus:
? 4924964562 (Eingabe)
Ausgabe:
Schritt 25199890 von 629997266 ( 4 Prozent)
-
long ist bei den meisten compilern ein 32bit typ.
64 bit kriegst du mit long long int.
im VS kannst du auch __int64 benutzen.
es empfiehlt sich sowiso eine headerdatei mit typedefs zu erzeugen.
da kann man zur not compilerswitches einbauen und sicher gehen, dass immer die typen benutzt werden, die man auch wollte.
Außerdem erspart es einen die schreibarbeit wie unsigned long long inthier ein Vorschlag:
MyStdTypes.h
#ifndef __MyStdTypes_h__ #define __MyStdTypes_h__ typedef signed char sint8; typedef unsigned char uint8; typedef signed short sint16; typedef unsigned short uint16; typedef signed int sint32; typedef unsigned int uint32; typedef signed long long int sint64; typedef unsigned long long int uint64; typedef float float32; typedef double float64; #endif // __MyStdTypes_h__
-
vlad_tepesch schrieb:
hier ein Vorschlag:
Der schon nur Systemabhängig funktioniert...
-
Mit unsigned long long int scheint das Programm auch langamer zu laufen als nur mit unsigned long int, oder bilde ich mir das nur ein?
-
andy89 schrieb:
Mit unsigned long long int scheint das Programm auch langamer zu laufen als nur mit unsigned long int, oder bilde ich mir das nur ein?
Das kann durchaus sein, abhängig von der OS-Unterstützung und den Prozessor (Registerbreiten...). Wenn mehr Takte für den Datentyp nötig sind, kann das ggf. etwas ausmachen...
-
andy89 schrieb:
Allerdings geht es da auch irgendwann nicht weiter....
tja, so ist das halt. es gibt immer eine grenze. mit 32-bit unsigned ints kannst du aber immerhin schon über 40 mio. schritte anzeigen. mit 64-bit dürfte der bereich sicher für die überwiegende mehrheit aller denkbaren anwendungen ausreichen.
andy89 schrieb:
Mit unsigned long long int scheint das Programm auch langamer zu laufen als nur mit unsigned long int, oder bilde ich mir das nur ein?
hängt vom system und vom compiler ab. am schnellsten dürfte es mit dem datentyp laufen, der genauso groß ist wie die wortbreite deines computers. vermutlich
unsigned int.
-
asc schrieb:
vlad_tepesch schrieb:
hier ein Vorschlag:
Der schon nur Systemabhängig funktioniert...
wie gesagt, an der stelle, kann man compilerweichen einbauen wie:
#ifndef __MyStdTypes_h__ #define __MyStdTypes_h__ #ifdef _MSC_VER typedef signed char sint8; typedef unsigned char uint8; typedef signed short sint16; typedef unsigned short uint16; typedef signed int sint32; typedef unsigned int uint32; typedef signed __int64 sint64; typedef unsigned __int64 uint64; typedef float float32; typedef double float64; #elsif _GCC typedef signed char sint8; typedef unsigned char uint8; typedef signed short sint16; typedef unsigned short uint16; typedef signed int sint32; typedef unsigned int uint32; typedef signed long long int sint64; typedef unsigned long long int uint64; #elsif __xyz typedef signed char sint8; typedef unsigned char uint8; typedef signed short sint16; typedef unsigned short uint16; typedef signed int sint32; typedef unsigned int uint32; // kann kein int64 //typedef signed long long int sint64; //typedef unsigned long long int uint64; #endif #endif // __MyStdTypes_h__
-
Mir ist wieder was neues eingefallen:
Aufruf in der main()
if (pruef(schritt, anzahl) == 1) { fortschritt(schritt, anzahl); }Und die Funktionen:
int pruef(ULLONG schr, ULLONG anz) { if ( schr%(anz/25) == 0) return 1; else return 0; } void fortschritt(double schr, double anz) { { /* Fortschrittsanzeigen; absolutund prozentual */ cout << "Schritt " << long (schr) << " von " << anz; cout << " ( " << schr*100/anz << " Prozent)" << endl; } }Wobei ullong unsigned long long ist.
Ich hab versucht, der pruef-Funktion long-Werte zu übergeben, dann ist da aber wieder dieses Problem mit der Wertüberschreitung...Ich überlege eigentlich, ob das mit Schritt x von y überhaupt sinnvoll ist.
Ich könnt mir die Fortschrittsanzeige auch so vorstellen:25% |==============........................|
Das müsste afaik mit Füllzeichen hinzubekommen sein, iwie so:
cout << proz << "% |" << setw(x) << setfill ('=') << "|" << endl;Wobei ich für x eine Schleife bauen würde...
EDIT.
Ausschnitt aus der main:
y++; if (y%1000000 == 0) { fortschritt(schritt, anzahl, y); // Damit y nicht irgendwann überläuft.... y = 0; }Und die Funktion:
void fortschritt(double schr, double anz, long y) { { /* Fortschrittsanzeigen; absolutund prozentual */ cout << schr*100/anz << "% |"; cout << setw(y) << setfill('=') << "" << setw(25-y) << setfill('.') << "|" << "\r"; } }Naja, das haut nicht ganz hin, wenn ich das ausführe füllen massenweise =s das Terminal....
EDIT2.
Ja, ich habs gemerkt, die Feldbreite wird auf 1 Million gesetzt...
Heut scheint irgendwie nicht mein Tag zu sein

-
Sorry dass ich kein edit mache...
So, ich bin jetzt auf folgende Lösung gekommen:
innerhalb einer Schleife in der main:
y++; if (y%1000000 == 0) { fortschritt(schritt, anzahl, y); // Damit y nicht irgendwann überläuft.... y = 0; }und:
void fortschritt(double schr, double anz, long y) { { int proz; /* Fortschrittsanzeigen; absolut und prozentual */ proz = (schr)*100/anz; cout << proz << "% |"; cout << setw(proz/4) << setfill('=') << "" << setw(25-(proz/4)) << setfill('.') << "|" << "\r"; } }Nun.... unter Windows funktionier die Fortschrittsanzeige richtig schön, bei Eingabe von 1e8 (100*1 Mio) zählt es jedes Prozent durch...
Nur unter Linux (gnome-terminal, xterm) geht es nicht ganz so gut, da dauert es erst einmal eine ganze Weile bis der Statusbalken erscheint, und dann zählt es auch ziemlich ruckartig... (33-66-99)...
Hat jemand eine Ahnung woran das liegen könnte?
EDIT:
Der Code aus der main-Funktion befindet sich übrigens innerhalb einer for-Schleife (sonst würde der Code ja wenig Sinn machen)
Lösung
Ein cout.flush() am Ende der Fortschrittsfunktion