Variablendeklaration, Berechnung in C

Neue Frage »

Auf diesen Beitrag antworten »
Jeynny Variablendeklaration, Berechnung in C

Meine Frage:
Gegeben sind folgende in der Programmiersprache C erstellten Variablendeklarationen:

long i, j, k;
double a, b;
j=3.; k=2
b=2;

Berechnen Sie

a) den Wert von i in den Ausdrücken:

a1) i=j/k*j;
a2) i=k/j*j;
a3) i=b*k/j;
a4) i=k/j*b;

b) den Wert von a in den Ausdrücken

b1) a=j/k;
b2) a=1. *j/k;
b3) a=k/j;
b4) a=b*k/j;

Meine Ideen:
Und bin noch eine totale Anfängerin und beschäftige mich mit den simplen Fragen.

Es geht doch darum, dass ich den definierten Variablen, einen Wert zuweisen soll mit einer bestimmten Genauigkeit.

Ich verstehe aber nicht genau wie ich das berechnen soll.

long ist 4 Byte groß und hat einen Wertebereich von ?2147483648 bis +2147483647.
double hat eine doppelte Genauigkeit

Ich habe mehrere Fragen:
Was bedeutet das Pünktchen nach j=3. oder a=1. ?
Und wie berechne ich die Ausdrücke dann? Ich meine ich habe zwei vorkommende Variablentypen mit unterschiedlichem Zahlenbereich wo quasi jede Ziffer angenommen werden kann und soll das mit 3 multiplizieren und was soll da rauskommen?

z.B. a1) i=long/2*long = 1/2 ? Ist das so gemeint?
bei a2) j*j=long*long ?
usw. Ich blicke da irgendwie nicht durch unglücklich Wäre sehr dankbar wenn es mir jemand erklären könnte.

Grüße

Jenny
 
Auf diesen Beitrag antworten »
eulerscheZahl

j=3. ist eine Kurzschreibweise für j=3.0. Da j eine Ganzzahl ist, wird der Teil nach dem Komma aber sowieso abgeschnitten.

i=j/k*j;
hier werden zunächst die Werte für j und k eingesetzt:
i = 3/2 * 3
Dann wird mit den gängigen Rechenregeln (Klammern zuerst, Punkt vor Strich, von links nach rechts) ausgewertet. Also zuerst 3/2. Das gibt 1.5. Allerdings sind j und k beide vom Typ long. Also ist auch j/k ein long. Deshalb ist 3/2=1.
Das wird dann mit j=3 multipliziert. Also gilt i=3.

Das kannst du übrigens auch selbst testen:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
#include <stdio.h>

int main(int argc, char const *argv[]) {
	long i, j, k;
	double a, b;
	j=3.; k=2;
	b=2;
	i=j/k*j; printf("a1: %ld\n", i);
	return 0;
}
Auf diesen Beitrag antworten »
Jeynny

Hey eulerscheZahl, deine Antwort hat mir schon sehr geholfen. Ich habe mir den Code im Compiler übersetzen lassen und habe dann geschaut was herauskommt, jedoch habe ich noch einige Fragen.

Ich nehme an, dass was die Ergebnisse bei a1 bis a4 angeht, Kommazahlen immer abgerundet werden auf die ganze Zahl.

a1) = 1
a2) = 0
a3) = 1
a4) = 0

Zitat:
code:
1:
i=j/k*j; printf("a1: %ld\n", i);


Was genau sagt mir die Zeile? Print ist der Ausgabebefehl, wo jetzt drin steht die Variablenspezifikation durch das Prozentzeichen und dann der Zeilenumbruch und dann noch das i.

Ich wollte jetzt die anderen Teilaufgaben überprüfen doch da kommt immer Null heraus und das kann nicht sein. Was genau ist das ld und außerhalb den Einführungszeichen das Komma, i? Wenn ich da das a einsetze kommen da wilde Zahlen heraus. Da weiß ich nicht so recht weiter unglücklich

Ich danke recht herzlich!

Jenny
Auf diesen Beitrag antworten »
eulerscheZahl

Kommazahlen werden bei Rechnungen mit Ganzzahlen immer abgerundet.

printf:
Als erstes wird ein string übergeben (innerhalb der ""). Hier kannst du ganz normal Text schreiben, der dann so ausgegeben wird. Sonderzeichen sind z.B. \n (Zeilenumbruch) oder \t (Tabulator).
Wenn du Variablen ausgeben willst, musst du in den string mit %... kenntlich machen, dass dort eine Variable eingesetzt wird.
Dafür gibt es verschiedene Ausgabemöglichkeiten:
%d: int
%ld: long int
%f: float
%lf: long float (=double)
%.3f: float mit 3 Nachkommastellen
um nur ein paar zu nennen. Mehr HIER. Wenn du eine Gleitpunktzahl mit %ld ausgeben willst, kommt nichts sinnvolles heraus.
Das sind aber nur Platzhalter. Um festzulegen, was da reinkommt, musst du nach dem string noch die entsprechenden Variablen in der Reihenfolge schreiben, in der du sie ausgeben willst.
 
Auf diesen Beitrag antworten »
Jeynny

Okay vielen Dank! Ist schon klarer geworden. Dann muss ich bei der zweiten Berechnung %lf für double nehmen nach dem string?

Ich bekomme dann folgende Ergebnisse:

b1) 0,000
b2) 1,500
b3) 0,000
b4) 1,333

Stimmen diese?

Jenny
Auf diesen Beitrag antworten »
eulerscheZahl

Damit ich nicht so viel scrollen muss:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
long i, j, k;
double a, b;
j=3.; k=2
b=2;

a1) i=j/k*j;
a2) i=k/j*j;
a3) i=b*k/j;
a4) i=k/j*b;

b1) a=j/k;
b2) a=1. *j/k;
b3) a=k/j;
b4) a=b*k/j;


b1) j/k = 3/2 = 1
die anderen passen.
Auf diesen Beitrag antworten »
Jeynny

Hallo,

ich habe meine alten Klausuraufgaben ausgepackt und komme bei b1 nicht auf 1.000

Ich habe folgenden Code compiliert:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#include <stdio.h>

    int main(int argc, char const *argv[]) {
	long i, j, k;
	double a, b;
	j=3.; k=2;
	b=2;
	a=j/k; printf("a1: %lf \n", i);
	return 0;
    }

Und bekomme anstatt 1.000 immer 0.000000 heraus?

Könnte mir da jemand helfen und sagen was ich falsch mache?

Grüße

Jenny
Auf diesen Beitrag antworten »
as_string

Du gibst den Wert der Variablen i aus, den Du aber noch nirgends definiert hast.
Wenn Du den Wert von a ausgeben willst, musst Du a auch in das printf() schreiben und im Formqtstring ein %d statt %lf dafür schreiben.

Gruß
Marco
Auf diesen Beitrag antworten »
Jeynny

Morgen Marco,

ohje. Danke für den Hinweis, ich saß gestern den halben Tag dran und fragte mich was ich doch falsch mache. Dabei muss ich die Ausgabe an die Formatspezifikation anpassen... Danke Daumen hoch
Hoffe, dass sich so ein Fehler in meinem Kopf verankert und ich ihn nie wieder mache.

Wie viele genaue Stellen, also richtige Stellen werden mir denn bei einer double - Rechnung angezeigt? Angezeigt wird ja immer mehr als verlangt, aber bis wohin geht die Genauigkeit?

Lieben Dank,

Jenny
Auf diesen Beitrag antworten »
as_string

Zitat:
Original von Jeynny
Wie viele genaue Stellen, also richtige Stellen werden mir denn bei einer double - Rechnung angezeigt? Angezeigt wird ja immer mehr als verlangt, aber bis wohin geht die Genauigkeit?

Ich bin mir jetzt nicht ganz sicher, ob das Deine Frage ist, aber ich habe hier:
http://www.teach.cs.toronto.edu/~ajr/209/notes/printf.html
das hier gefunden:
code:
1:
lf	double [footnote]	number with six digits of precision

Also wohl nur sechs Stellen.
Man kann das ja noch beeinflussen , indem man modifier verwendet. Aber da müsste ich mal erst selbst ausprobieren, wie sich das im Detail auswirkt.

Gruß
Marco
Auf diesen Beitrag antworten »
Jeynny

Hallo Marco!

Zitat:
Original von as_string
Also wohl nur sechs Stellen.
Man kann das ja noch beeinflussen , indem man modifier verwendet. Aber da müsste ich mal erst selbst ausprobieren, wie sich das im Detail auswirkt.

Ja es sind 6 Stellen, es werden auch immer nur 6 Stellen angezeigt, wenn man es ausgibt. Ich verstehe jedoch noch nicht ganz wie gerechnet wird verwirrt

Es kommt ja wie schon festgestellt:
b1=1.000000
b2=1.500000
b3=0.000000
b4=1.333333

heraus. Ich versuche jetzt nachzuvollziehen wieso die Ergebnisse so herauskommen.

b1)
ich teile zwei integer-Zahlen, der Rest wird also weggeschnitten 3/2 = 1.5 => 1.000000

b2)
ich multipliziere integerzahl also j =3.0 mit einer 1. einer Fließkommazahl? Dann teile ich durch k=2 einer integerzahl und erhalte 1.500000 und ich frage mich wieso jetzt nicht die Nachkommastelle abgeschnitten wird?

b3)
Ich teile zwei integerzahlen 2/3 der Rest wird abgeschnitten, also bekomme ich 0.000000

b4)
ich multipliziere b=2 (eine Fließkommazahl) mit einer integerzahl (k=2) und erhalte 4. Und 4 teile ich durch die integerzahl 3. und erhalte 1.333333.

Mir ist noch nicht ganz bewusst wie die Prozedur abläuft, bzw. wie die Wirkung der Datentypen ist. Ich rechne immer von links nach rechts und berücksichtige Klammern und Punkt-Vor-Strich-Rechnung. Ich verstehe jedoch nicht wieso wenn ich zwei integerzahlen durcheinander dividiere wie bei b3) also 2/3, der Rest abgeschnitten wird, wenn ich es doch als a Speicher, also einen Fließkommadatentyp?

Grüße

Jenny
Auf diesen Beitrag antworten »
as_string

Zitat:
Original von Jeynny
b1)
ich teile zwei integer-Zahlen, der Rest wird also weggeschnitten 3/2 = 1.5 => 1.000000

Genau: Beide Operanden sind Integer, deshalb geht C von einer Ganzzahl-Division aus, was zum Abschneiden führt.
Zitat:
Original von Jeynny
b2)
ich multipliziere integerzahl also j =3.0 mit einer 1. einer Fließkommazahl? Dann teile ich durch k=2 einer integerzahl und erhalte 1.500000 und ich frage mich wieso jetzt nicht die Nachkommastelle abgeschnitten wird?

Die Auswertung geht von links nach rechts vor (wenn keine Klammern im Spiel sind und Punkt-vor-Strich auch erstmal außen vor gelassen). Da gibt es eine Gleitkommazahl (im Deutschen sagt man eigentlich nicht Fließkomma-Zahl, das ist nur schlecht vom Englischen "float" abgeleitet) und ein Mal-Zeichen und eine Integerzahl. Da (mindestens) ein Operand eine Gleitkommazahl ist, wird der andere Operand auch zuerst in eine Gleitkomma-Zahl umgewandelt und dann erst die Operation mit Gleitkomma-Logik ausgeführt. Dabei kommt ein Zwischenergebnis raus, nämlich gerade der Wert von j, allerdings als Gleitkommazahl.
Im nächsten Schritt hat man das eben ausgerechnete Zwischenergebnis, das ja eine Gleitkommazahl ist, und teilt das durch eine Integer-Zahl. Auch hier wieder: Wenn mindestens ein Operand Float ist, wird alles in Float (oder Double?) umgewandelt, was noch Integer ist. Also bevor irgendwas gerechnet wir, wird k schon in eine Gleitkommazahl umgewandelt und die Division wird in Gleitkomma-Logik ausgeführt und genau das kommt auch als Ergebnis raus.
Zitat:
Original von Jeynny
b3)
Ich teile zwei integerzahlen 2/3 der Rest wird abgeschnitten, also bekomme ich 0.000000

OK.
Zitat:
Original von Jeynny
b4)
ich multipliziere b=2 (eine Fließkommazahl) mit einer integerzahl (k=2) und erhalte 4. Und 4 teile ich durch die integerzahl 3. und erhalte 1.333333.

Mir ist noch nicht ganz bewusst wie die Prozedur abläuft, bzw. wie die Wirkung der Datentypen ist. Ich rechne immer von links nach rechts und berücksichtige Klammern und Punkt-Vor-Strich-Rechnung. Ich verstehe jedoch nicht wieso wenn ich zwei integerzahlen durcheinander dividiere wie bei b3) also 2/3, der Rest abgeschnitten wird, wenn ich es doch als a Speicher, also einen Fließkommadatentyp?

Nochmal zusammen gefasst:
Die Auswertung funktioniert so: Zuerst wird mit Klammern und Punkt-vor-Strich (Operator-Präzedenz im Allgemeinen) und links nach rechts im Zweifelsfall eine Reihenfolge ermittelt. Dann werden immer die Operatoren mit ihren Operanden ermittelt (das können häufig zwei sein, wie bei +, -, *, / (und andere), manchmal auch nur einer, selten auch mal drei).
Bei +, -, *, / (und vielleicht auch bei anderen, weiß ich gerade auch nicht auswendig) gibt es immer zwei Operanden und was die Operatoren genau machen, wird über den Typ der Operanden ermittelt:
Ist mindestens ein Operand eine Gleitkommazahl, wird die andere auch in eine gewandelt, wenn es vorher noch keine war. Dann wird der passende Operator ausgeführt. Die machen für Gleitkomma-Zahlen was anderes als für Ganzzahlen. Zumindest intern ist die Rechnung komplett anders. Das Ergebnis entspricht immer dem Typ des Operators, der letztlich ausgewählt wurde (also: sobald ein Operand ein Gleitkommazahl ist, wird immer der Gleitkomma-Operator ausgewählt und das Ergebnis ist dann immer auch eine Gleitkommazahl. Nur wenn beide Operanden Ganzzahlen sind, kommt der Ganzzahl-Operator zum Zuge und das Ergebnis ist eine Ganzzahl).
Das Ergebnis wird als Zwischenergebnis verwendet und die beiden Operanden und der Operator wird quasi für die weitere Rechnung mit diesem Zwischenergebnis ersetzt, also mit einer Gleitkommazahl, wenn auch nur ein Operand eine war.

Am Ende kommt dann eine Ganzzahl oder eine Gleitkommazahl raus, die einer Variablen eines bestimmten, unter Umständen anderen Typs zugewiesen wird. Da macht C dann automatisch eine Umwandlung, aber erst nachdem der gesamte Ausdruck rechts ausgewertet worden ist. Vorher schaut C noch nichtmal auf den Typ links.
Das kann funktionieren, muss aber nicht immer. Von Integer zu Gleitkomma sollte aber immer gehen, umgekehrt bin ich gerade gar nicht sicher, müsste man ausprobieren. Wenn aber das Ergebnis auf der rechten Seite ein Integer war, wird der erst bei der Zuweisung wieder in eine Gleitkomma-Zahl umgewandelt und hat dann schon gar keine Nachkomme-Stellen mehr. Diese Umwandlung kann die dann auch nicht wieder herzaubern.

Gruß
Marco
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »