Forum: PC-Programmierung floor, ceil, modf -> Aufrunden/Abrunden


von DjangoG (Gast)


Lesenswert?

Hi Leute,

ich habe eine Aufgabe die ich lösen soll und komm nicht ganz weiter:

Erstellen Sie ein C-Programm, das eine Gleitpunktzahl in einer Variablen 
und eine Anzahl von Nachkommastellen in einer anderen Variablen 
definiert.
Das Programm soll nun die erste Zahl auf die angegebenen Anzahl von 
Nachkommastellen auf- und abgerundet ausgeben.
Zusätzlich soll dieses Programm auch noch die Zahl auf die angegebenen 
Nachkommastellen be- grenzt ausgeben lassen, wobei es die Rundung den 
intern vorgegebenen Regeln überlässt.
Am Ende soll dieses Programm für die eingegebene Zahl noch die deutsche 
Schreibweise (mit Komma) ausgeben.

Mögliche Ausgaben dieses Programms sind:
/*
 * Gleitpunktzahl: 12.345678
 * Kommastellen runden: 4
 */
Abgerundet: 12.3456
Aufgerundet: 12.3457
Nach Rundungsregeln: 12.3457
In deutscher Schreibweise: 12,3457

Hinweis: Fügen Sie #include <math.h> hinzu. Dann können Sie die 
Funktionen floor, ceil und modf ver- wenden.
Zu floor und ceil lesen Sie unter
http://de.wikipedia.org/wiki/Abrundungsfunktion_und_Aufrundungsfunktion 
, was die beiden Funktionen für Sie berechnen.
Die Anweisung
nachkomma = modf(zahl,&vorkomma);
zerlegt die Zahl zahl in die Teile vor bzw. nach dem Komma und schreibt 
sie in die Variablen vorkomma bzw. nachkomma. (Das ominöse & vor 
vorkomma wird später erklärt!)

Weiß jemand damit etwas anzufangen???

: Verschoben durch User
von Karl H. (kbuchegg)


Lesenswert?

DjangoG schrieb:

> Weiß jemand damit etwas anzufangen???

Eigentlich schon.
So gut wie alle Schwierigkeiten sind in der Aufgabenstellung 
angesprochen und Lösungswege dafür aufgezeigt worden. Die 
Einzelinformationen müssen noch miteinander kombiniert werden und ein 
Programm dafür geschrieben werden.
Das wird vielleicht nicht auf Anhieb alles richtig machen, aber mit ein 
wenig Geduld und Spucke und dem Verständnis dessen, was die einzelnen 
angesprochenen Funktionen machen, ist es eigentlich kein Problem diese 
Aufgabe zu lösen.

Das einzige was vielleicht noch erwähnt werden sollte, ist die simple 
Tatsache, dass man mit geeigneten Multiplikationen mit Vielfachen von 
10, ein Komma auch verschieben kann.

So wird aus  123.456789 durch Multiplikation mit 10000 die Zahl 
1234567.89 in der die ersten 4 ursprünglichen Nachkommastellen jetzt 
alle vor dem Komma sitzen, was die Anwendung von floor bzw. ceil 
deutlich erleichtern dürfte, wenn man auf n Kommastellen (in diesem 
Beispiel wäre n dann 4 gewesen) runden soll (egal ob auf- oder abrunden)

: Bearbeitet durch User
von Murkser (Gast)


Lesenswert?

DjangoG schrieb:
> Weiß jemand damit etwas anzufangen???

Ja.

von DjangoG (Gast)


Lesenswert?

So hab ich das jetzt mal versucht:
1
int main(int argc, char** argv) {
2
3
    double zahl = 12.345678,nachkomma, vorkomma,aufgerundet, abgerundet;
4
    
5
    nachkomma = modf(zahl ,&vorkomma);
6
7
    printf("Nachomma: %lf",nachkomma); 
8
    printf("\nVorkomma: %lf", vorkomma); 
9
    
10
    nachkomma = nachkomma *10000;    
11
    nachkomma = ceil(nachkomma) / 10000; 
12
    aufgerundet = nachkomma + vorkomma;
13
    
14
    
15
   //printf("Abgerundet: %lf", );
16
    printf("Aufgerundet: %.4lf",aufgerundet); 
17
    printf("\nNach Rundungsregel: %.4lf", zahl);
18
    //printf("\nIn deutscher Schreibweise: %lf,%lf",vorkomma, nachkomma );
19
    
20
    return (EXIT_SUCCESS);
21
}
Aber wenn ich das jetzt einmal durchgemacht habe, müsste ich ja wieder 
eine neue Variable für nachkomma definieren oder? Damit ich mit 
abgerundet weiter machen kann?
Ich hab erst vor kurzem mit C angefangen & programmiert habe ich vorher 
auch noch nie..

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

DjangoG schrieb:

> Aber wenn ich das jetzt einmal durchgemacht habe, müsste ich ja wieder
> eine neue Variable für nachkomma definieren oder? Damit ich mit
> abgerundet weiter machen kann?

Allerdings zwingt dich niemand, dass du dir den Wert in nachkomma hier
1
    nachkomma = ceil(nachkomma) / 10000; 
2
    aufgerundet = nachkomma + vorkomma;
zerstörst.

Du kannst das ja auch so schreiben ...
1
    aufgerundet = vorkomma + ceil(nachkomma) / 10000;
...
wodurch dir der ursprüngliche Wert in nachkomma erhalten bleibt und für 
die nächste Rundungsvariante zur Verfügung steht.
Man darf durchaus auch komplexere Ausdrücke schreiben und muss nicht 
immer auf der rechten Seite einer Zuweisung nur einfache Ausdrücke mit 
lediglich einer einzigen Operation haben.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Mal schauen, wie lange es dauert, bis du folgenden code schaffst zum 
laufen zu bringen. Wenn du ihn verstehst, kennst du datentypen.

Ungetestet:
1
void runden(double x,double &abgerundet,double &aufgerundet,double &arithmatisch,int s=2,int base=10){
2
3
long double n=pow(base,s);
4
5
 abgerundet = (long long)(n*x); // floor(n*x)
6
 aufgerundet = (n*x-abgerundet==0)?abgerundet:abgerundet+1l;
7
 arithmatisch = (long long)(n*x+0.500001l); // round(n*x)
8
9
abgerundet /= n;
10
aufgerundet /= n;
11
arithmatisch /= n;
12
13
}

: Bearbeitet durch User
von DjangoG (Gast)


Lesenswert?

Danke für die Hilfe!

Wusste nur nicht wie ich das mit dem normalen Komma lösen soll.
1
int main(int argc, char** argv) {
2
3
    double zahl = 12.345678,nachkomma, vorkomma,aufgerundet, abgerundet;
4
    
5
    nachkomma = modf(zahl ,&vorkomma);
6
    nachkomma = nachkomma *10000;
7
    
8
    abgerundet = vorkomma + floor(nachkomma) / 10000;
9
    aufgerundet = vorkomma + ceil(nachkomma) / 10000;
10
    
11
    
12
    printf("\nGleitpunktzahl: %lf\n",zahl);
13
    printf("\nAbgerundet: %.4lf", abgerundet);
14
    printf("\nAufgerundet: %.4lf",aufgerundet); 
15
    printf("\nNach Rundungsregel: %.4lf", zahl);
16
    printf("\nIn deutscher Schreibweise: %.0lf,%.0lf\n",vorkomma, nachkomma );
17
    
18
    return (EXIT_SUCCESS);
19
}

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Test das mal mit 1.0023456789 und achte auf die deutsche Ausgabe.

Die Anzahl der Nachkommastellen soll auch variabel sein.

Was mit printf geht, kannst du hier nachlesen: 
http://www.cplusplus.com/reference/cstdio/printf/

von DjangoG (Gast)


Lesenswert?

Danke für den Tipp. Das funktioniert so nicht, da hast du Recht!

Aber ich weiß ehrlich gesagt auch nicht wie es ich sonst machen soll.
Kann mir jemand sagen wie es geht??

von Brater (Gast)


Lesenswert?

Da gibts verschiedene Ansätze... der trivialste wäre das Aufteilen der 
Zahl in Vor- und Nachkommastellen. Dazwischen schreibt man den Punkt von 
Hand.

Bei cout muss man das über imbue lösen, indem man den Operator für die 
Kommastelle überschreibt.

Manche Leute sind echt zu faul zu googlen - sorry aber das ist echt kein 
Hexenwerk.

von DjangoG (Gast)


Lesenswert?

Was habe ich denn gemacht? Hast du dir überhaupt meinen Ansatz angeguckt 
bevor du sagst "Manche Leute sind echt zu faul zu googlen - sorry aber 
das ist echt kein"

Ich hab es in Vor und Nachkomma Anteil aufgeteilt, wie man an meinem 
COde sieht aber das scheint ja nur so lange zu gehen, bis Nullen direkt 
nach dem Komma folgen....

Und gegooglet habe ich genug aber "einfache" Ansätze habe ich nicht 
gefunden! Nur welche die ich nicht verstanden habe.

von Brater (Gast)


Lesenswert?

Google Ergebnis Nummer 3: 
http://stackoverflow.com/questions/14753505/c-c-printf-use-commas-instead-of-dots-as-decimal-separator

im nächsten Schritt könntest du z.B. mal die Funktion locale genauer 
anschauen.

von Dirk B. (dirkb2)


Lesenswert?

Du kannst bei printf auch führende Nullen mit ausgeben:
1
printf("\nIn deutscher Schreibweise: %.0f,%04.0%f\n",vorkomma, nachkomma );
Ist ein etwas blöd, wenn man die Stellen Variabel machen will.
Darum gibt es bie printf den * Modifier. da kannst du die Anzahl als 
Parameter übergeben.
1
printf("\nIn deutscher Schreibweise: %.0f,%0*.0%f\n",vorkomma, 4, nachkomma );
Der Formatspecifier %f ist bei printf für double und float da. (nicht 
bei scanf)

Und teste auch mal negative Werte.

von DjangoG (Gast)


Lesenswert?

Kriege es immer noch nicht richtig hin mit dem Komma.

Wenn ich das so eingebe wie du geschrieben hast:

printf("\nIn deutscher Schreibweise: %.0f,%0*.0%f\n",vorkomma, 4, 
nachkomma );

Bekomme ich folgendes:

"In deutscher Schreibweise: 12,000%f"

von Karl H. (kbuchegg)


Lesenswert?

DjangoG schrieb:
> Kriege es immer noch nicht richtig hin mit dem Komma.
>
> Wenn ich das so eingebe wie du geschrieben hast:

Ein bischen musst du selbst auch nachdenken bzw. dein Wissen einsetzen.
Im Formatstring sind 3 Stück %, aber du hast keine 3 Werte, die in diese 
3 % passen würden. (die 4 wird ja vom * im Formatstring konsumiert).


Rechne immer damit, dass in Forenbeiträgen auch Tippfehler sein können. 
Je banaler ein Stück Code ist, desto eher enthält er Tippfehler, weil 
der Antwortende den Code vor dem Versenden nicht testet, eben weil er so 
banal ist.

Um mitdenken und nicht einfach gedankenlos irgendwelche Dinge aus einem 
Forum übernehmen wirst du daher nicht herumkommen. Und das gilt nicht 
nur für Antworten aus einem Forum sondern für die ganze Programmiererei 
insgesammt. Wenn schon zu nichts anderem, dann erzieht das Programmieren 
zu exakter Beobachtung und dem Beachten von Kleinigkeiten. Denn Computer 
sind da gnadenlos. Was bei zwischenmenschlicher Kommunikation problemlos 
durchgeht (weil das Gehirn des Gegenübers das alles ausgleicht), führt 
in der Programmierung zu nicht funktionierenden Programmen.


Wenn du in deiner Ausgabe das hier siehst
1
       12,000%f

also ein % Zeichen, das da nicht sein sollte, dann kannst du 100 zu 1 
darauf wetten, das im Formatstring irgendwas durcheinandergekommen ist, 
und die Anzahl der %xxxxx Angaben nicht mit der Anzahl der an printf 
übergebenen Werte nach dem Formatstring übereinstimmt.
Das fällt genau in die Kategorie, die ich mit 'exaktem Beobachten' 
meine. Kleinigkeiten, die einem Hinweise geben. Das können Kleinigkeiten 
in den Programmausgaben sein, das können aber auch Kleinigkeiten in der 
realen Welt sein, die man im Programm modellieren soll. Das können aber 
auch Kleinigkeiten in dem zu lernden Stoff sein, indem man zb bemerkt, 
dass im Formatstring die Platzhalter immer mit einem % beginnen und mit 
einem oder mehreren Buchstaben enden. Der Buchstabe bezieht sich auf den 
Datentyp des weiter hinten im Funktionsaufruf stehenden Argumentes an 
printf. Zwischen % und Buchstabe stehen Angaben, die die Art und Weise 
der Ausgabe modifizieren. Aber das Prinzip %xxx_Buchstabe bleibt in 
allen Fällen immer erhalten. Eine Angabe von "%0*.0%f" kann daher, rein 
schon aus dieser Betrachtung heraus, nicht korrekt sein. Denn zwischen % 
und Buchstabe kann es keinen weiteren % geben.

: Bearbeitet durch User
von DjangoG (Gast)


Lesenswert?

Vielen Dank. Habe es jetzt hinbekommen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.