Forum: Mikrocontroller und Digitale Elektronik Datentypen in Operationen


von André W. (sefiroth)


Lesenswert?

Hallo zusammen!

Ein häufiges Problem bei Rechnungen ist ja der vergessene Datentyp von 
Operanden bei Rechnungen, wie in dem Beispiel:
1
int i = 5;
2
int j = 2;
3
4
double r = i / j;
5
6
// Ergebnis in r ist 2 und nicht 2.5 wie vielleicht erwartet, da beide Operanden vom Typ int sind und daher auch das Ergebnis der Division vom Typ int.

Das wird hier auch sehr gut beschrieben und sollte soweit auch allgemein 
bekannt sein:
http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen

Was ich gerne fragen wollte ist, wie es sich mit komplexeren Rechnungen 
verhält. Genügt es wenn irgendein Operand einen Typecast bekommt, damit 
die gesamte Rechnung in diesem Type durchgeführt wird? Oder muss es (wie 
ich bisher angenommen habe) immer der zuerst vom Compiler angefasste 
Operand sein?

Mal folgende Beispielrechnung angenommen:
1
double r = (5 / 2) + (7 / (3 / 2) );

Wie würdet Ihr sie typecasten, damit sie sauber berechnet wird? Mein 
Vorschlag wäre:
1
double r = ( (double) 5 / 2) + (7 / ( (double) 3 / 2) );

von Klaus W. (mfgkw)


Lesenswert?

Es reicht, wenn einer z.B. double ist, damit die Rechnung in double 
stattfindet - egal welcher der beiden.

Es ist also egal, ob r=1.0/2 oder r=1/2.0 oder r=1.0/2.0 gerechnet wird.

André Wippich schrieb:
> Wie würdet Ihr sie typecasten, damit sie sauber berechnet wird? Mein
> Vorschlag wäre:double r = ( (double) 5 / 2) + (7 / ( (double) 3 / 2) );

Meiner: r = ( 5.0 / 2.0) + (7.0 / (3.0 / 2.0) );

von Tom (Gast)


Lesenswert?

> double r = ( (double) 5 / 2) + (7 / ( (double) 3 / 2) );

So ist es richtig. Alles wird double gerechnet.

> r = ( 5.0 / 2.0) + (7.0 / (3.0 / 2.0) );

So wird nur float gerechnet und dann dem double zugewiesen. Und der TO 
wollte das mit typecasts machen.

von Klaus W. (mfgkw)


Lesenswert?

Tom schrieb:
> So wird nur float gerechnet und dann dem double zugewiesen.

Das weißt du sicher?

von Klaus W. (mfgkw)


Lesenswert?

Nach C-Standard finden alle (Gleitklomma-)Berechnungen eh in
double statt (außer bei long double natürlich), und 1.0 ist
eine double-Konstante.


Beim avr-gcc kommt dazu, daß float ebenso wie double 4 Byte
haben und einfach gleich sind.

von André W. (sefiroth)


Lesenswert?

Aber Tom hat schon recht, ich wollte das gerne mit Typecasts machen. Die 
Zahlen habe ich nur als Vereinfachung verwendet, um nicht noch einen 
Haufen Variablen mit einführen zu müssen. Absicht der Frage war quasi 
wie viele Typecasts wirklich nötig sind.

von Karl H. (kbuchegg)


Lesenswert?

André Wippich schrieb:

> Was ich gerne fragen wollte ist, wie es sich mit komplexeren Rechnungen
> verhält.

Ich denke deine eigentliche Frage ist noch nicht wirklich beantwortet.

Auch ein komplexere Berechnung ist letztenendes ja nur eine Abfolge von 
einfachen Operationen. Nur ist halt das Ergebnis einer Operation 
wiederrum Operand für die nächste Operation.

Und in allen Stufen wird erneut entschieden: linker Operand, rechter 
Operand, wie wird die Operation implementiert.


d.h. die Berechnung

  int a = 5, b = 8;
  double c;

  c = 8.0 + b * a;

laut den Rechenregeln, wird so gerechnet

    b * a   ->   Zwischenergebnis
                         |
                         |
                         +--->  + 8.0

b ist ein int, a ist ein int. Also erfolgt da eine int Multiplikation. 
Das Ergebnis davon ist wieder int.

Also ist Zwischenergebnis vom Datentyp int.

Um dieses mit 8.0 (einem double) zu addieren, wird dieses 
Zwischenergebnis zu einem double umgeformt und die Addition 
durchgeführt. Das Ergebnis hat dann ebenfalls Datentyp double und muss 
nicht weiter behandelt werden um an c zugewiesen zu werden.

Also immer einfach nur den Rechenregeln folgen: In welcher Reihenfolge 
wird ausgewertet, welche Datentypen sind beteiligt, welche Datentypen 
entstehen für die Zwischenergebnisse, was passiert mit den ZwischenErg. 
weiter?

So kannst du jeden Ausdruck analysieren.

von André W. (sefiroth)


Lesenswert?

Vielen Dank! Genau das wollte ich wissen :-)

von (prx) A. K. (prx)


Lesenswert?

Klaus Wachtler schrieb:

> Nach C-Standard finden alle (Gleitklomma-)Berechnungen eh in
> double statt

Das war zwar anno K&R so, aber bereits in ANSI-C wurde das gestrichen 
und float+float darf als float gerechnet werden (die Konstanten bleiben 
natürlich double, sofern nicht explizit spezifiziert).

"First, if either operand has type long double, the other operand is 
converted to long double.  Otherwise, if either operand has type double, 
the other operand is converted to double.  Otherwise, if either operand 
has type float, the other operand is converted to float."

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Klaus Wachtler schrieb:
>
>> Nach C-Standard finden alle (Gleitklomma-)Berechnungen eh in
>> double statt
>
> Das war zwar anno K&R so, aber bereits in ANSI-C wurde das gestrichen
> und float+float darf als float gerechnet werden (die Konstanten bleiben
> natürlich double, sofern nicht explizit spezifiziert).

das mag schon sein, nichts desto trotz ist 5.0 ein double

von (prx) A. K. (prx)


Lesenswert?

Genau das hatte ich eben doch auch geschrieben.

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.