Wie kommt es, dass im folgenden Ausschnitt
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
endet damit, dass man den Wert 2 hat, anstatt wie erwartet 2,3333. Wenn a
und b
doppelt sind, lautet die Antwort 2.333. Aber sicher, weil es c
bereits ein Double ist, hätte es mit ganzen Zahlen funktionieren sollen?
Wie kommt int/int=double
es, dass es nicht funktioniert?
c++
variables
double
integer-division
Jahoe
quelle
quelle
Antworten:
Dies liegt daran, dass Sie die Integer-Division-Version von verwenden
operator/
, die 2int
s dauert und eine zurückgibtint
. Um diedouble
Version zu verwenden, die a zurückgibtdouble
, muss mindestens eines derint
s explizit in a umgewandelt werdendouble
.quelle
a
undb
zudouble
für Klarheit einfach, aber es ist wirklich egal.static_cast<>
kam mir immer langatmig vor. Bei Primitiven besteht keine wirkliche Gefahr des Verwechselnsstatic_cast<>
undreinterpret_cast<>
Verwechselns.static_cast
in diesem Fall vorziehen, zu vermeiden und stattdessen eine Besetzung im C-Stil zu verwenden. Die Verwendung von Casts im C ++ - Stil hat hier keinen Vorteil, und sie überladen den Code viel mehr als Casts im C-Stil. Arithmetische Besetzung ist genau der Kontext, in dem Besetzungen im C-Stil perfekt und tatsächlich geeigneter sind als andere Besetzungen.double(b)
. Sie erkennen nicht immer, dass es sich um eine Konvertierung handelt, da sie genauso aussieht wie ein expliziter Konstruktoraufruf.Hier ist es:
a) Das Teilen von zwei
int
s führt immer eine ganzzahlige Division durch. Das Ergebnis vona/b
in Ihrem Fall kann also nur ein seinint
.Wenn Sie behalten
a
undb
alsint
s, aber sie vollständig teilen möchten , müssen Sie mindestens eine davon zum Verdoppeln wirken:(double)a/b
odera/(double)b
oder(double)a/(double)b
.b)
c
eindouble
, so kann sie akzeptieren einenint
Wert auf assignement: dieint
automatisch umgewandeltdouble
und übertragen aufc
.c) Denken Sie daran, dass bei der Zuweisung der Ausdruck rechts von zuerst
=
berechnet wird (gemäß Regel (a) oben und ohne Berücksichtigung der Variablen links von ) und dann der Variablen links von (gemäß ( b) oben). Ich glaube, das vervollständigt das Bild.=
=
quelle
Mit sehr wenigen Ausnahmen (ich kann mir nur eine vorstellen) bestimmt C ++ die gesamte Bedeutung eines Ausdrucks (oder Unterausdrucks) aus dem Ausdruck selbst. Was Sie mit den Ergebnissen des Ausdrucks machen, spielt keine Rolle. In Ihrem Fall ist im Ausdruck
a / b
keindouble
in Sicht; alles istint
. Der Compiler verwendet also die Ganzzahldivision. Erst wenn das Ergebnis vorliegt, wird überlegt, was damit zu tun ist, und es wird in konvertiertdouble
.quelle
&funcname
hängt davon ab, in welchen Typ Sie ihn umwandeln.c
ist einedouble
Variable, aber der ihr zugewiesene Wert ist einint
Wert, da er sich aus der Division von zweiint
s ergibt, wodurch Sie eine "ganzzahlige Division" erhalten (den Rest fallen lassen). Was also in der Zeile passiert,c=a/b
ista/b
wird ausgewertet, wodurch ein temporärer Typ erstellt wirdint
c
nach der Konvertierung in Typ zugewiesendouble
.Der Wert von
a/b
wird ohne Bezugnahme auf seinen Kontext (Zuordnung zudouble
) bestimmt.quelle
Wenn Sie zwei Ganzzahlen teilen, ist das Ergebnis eine Ganzzahl, unabhängig davon, ob Sie sie in einem Doppel speichern.
quelle
In der C ++ - Sprache wird das Ergebnis des Unterausdrucks niemals vom umgebenden Kontext beeinflusst (mit einigen seltenen Ausnahmen). Dies ist eines der Prinzipien, denen die Sprache sorgfältig folgt. Der Ausdruck
c = a / b
enthält einen unabhängigen Unterausdrucka / b
, der unabhängig von etwas außerhalb dieses Unterausdrucks interpretiert wird. Der Sprache ist es egal, dass Sie das Ergebnis später einem zuweisendouble
.a / b
ist eine ganzzahlige Division. Alles andere spielt keine Rolle. Sie werden sehen, dass dieses Prinzip in vielen Ecken der Sprachspezifikation befolgt wird. So funktioniert C ++ (und C).Ein Beispiel für eine oben erwähnte Ausnahme ist die Zuweisung / Initialisierung von Funktionszeigern in Situationen mit Funktionsüberladung
Dies ist ein Kontext, in dem die linke Seite einer Zuweisung / Initialisierung das Verhalten der rechten Seite beeinflusst. (Die Initialisierung des Verweises auf das Array verhindert auch den Zerfall des Array-Typs, was ein weiteres Beispiel für ein ähnliches Verhalten ist.) In allen anderen Fällen ignoriert die rechte Seite die linke Seite vollständig.
quelle
Der
/
Operator kann für die Ganzzahldivision oder die Gleitkommadivision verwendet werden. Sie geben ihm zwei ganzzahlige Operanden, also wird eine ganzzahlige Division durchgeführt, und dann wird das Ergebnis in einem Doppel gespeichert.quelle
Dies ist technisch sprachabhängig, aber fast alle Sprachen behandeln dieses Thema gleich. Wenn zwischen zwei Datentypen in einem Ausdruck eine Typinkongruenz besteht, versuchen die meisten Sprachen, die Daten auf einer Seite des Ausdrucks so umzuwandeln, dass sie
=
mit den Daten auf der anderen Seite gemäß einem Satz vordefinierter Regeln übereinstimmen.Wenn Sie zwei Zahlen desselben Typs (Ganzzahlen, Doppelte usw.) teilen, ist das Ergebnis immer vom gleichen Typ (also führt 'int / int' immer zu int).
In diesem Fall haben Sie,
double var = integer result
was das ganzzahlige Ergebnis nach der Berechnung auf ein Doppel umwandelt. In diesem Fall gehen die Bruchdaten bereits verloren. (Die meisten Sprachen führen dieses Casting durch, um Typungenauigkeiten zu vermeiden, ohne eine Ausnahme oder einen Fehler auszulösen.)Wenn Sie das Ergebnis als Doppel behalten möchten, möchten Sie eine Situation schaffen, in der Sie haben
double var = double result
Der einfachste Weg, dies zu tun, besteht darin, den Ausdruck auf der rechten Seite einer Gleichung zu zwingen, ihn zu verdoppeln:
c = a/(double)b
Die Trennung zwischen einer Ganzzahl und einem Doppel führt dazu, dass die Ganzzahl in das Doppel umgewandelt wird (beachten Sie, dass der Compiler beim Rechnen häufig auf den spezifischsten Datentyp "hochgespielt" wird, um Datenverlust zu vermeiden).
Nach dem Upcast
a
wird als Doppel beendet und jetzt haben Sie die Aufteilung zwischen zwei Doppel. Dadurch wird die gewünschte Unterteilung und Zuordnung erstellt.WIEDER, bitte beachten Sie, dass dies sprachspezifisch ist (und sogar compilerspezifisch sein kann), jedoch behandeln fast alle Sprachen (sicherlich alle, die mir auf den ersten Blick einfallen) dieses Beispiel identisch.
quelle
Wichtig ist, dass eines der Berechnungselemente ein Float-Double-Typ ist. Um ein doppeltes Ergebnis zu erhalten, müssen Sie dieses Element wie unten gezeigt umwandeln:
oder c = a / static_cast (b);
Oder Sie können es direkt erstellen ::
Beachten Sie, dass eines der Berechnungselemente die '.0' haben muss, um eine Division eines Float-Double-Typs durch eine Ganzzahl anzuzeigen. Andernfalls ist das Ergebnis auch Null, obwohl die Variable c ein Doppel ist.
quelle