c++ | Mathematische Schreibweise ungleich?!

Rofi

Erfahrenes Mitglied
Hi,

folgende Funktionen habe ich in einem Programm:
Code:
// Funktion Kraft steigern
int addProzent(int power, int prozent)
{
	 // return  (power * (1.0 + prozent / 100));
	return (power + power * prozent / 100);
}

// Funktion Geschwindigkeit steigern
double addProzent(double speed, int prozent)
{
	return (speed * (1.0 + prozent / 100.0));
}

// Funktion Kraft steigern: Der Wert „power“ soll um den Prozentsatz „prozent“ erhöht werden.

Benutze ich in der ersten Funktion mit den int-Werten obige Schreibweise, ist das Ergebnis bis auf den abgeschnittenen Kommawert korrekt, was aber in Ordnung ist!

Ist die Schreibweise aber wie die Kommentarzeile in derselben Funktion oder so wie in der Geschwindigkeits-steigern-Funktion, so kommen unerwünschte Ergebnisse heraus:

Wird z.Bsp.
power = 100 und prozent = 15 an die Funktion übergeben, so liefert sie als Ergebnis wieder 100 zurück!?

Wird für
power = 100 und prozent = 115 eingesetzt, wird 200 zurückgegeben!?




// Funktion Geschwindigkeit steigern: Der Wert „speed“ soll um den Prozentsatz „prozent“ erhöht werden.

Diese double-Funktion liefert mit der dargestellten Schreibweise korrekte Rückgabewerte!




Mathematisch liefern die beiden Schreibweisen

power * (1.0 + prozent / 100)
power + power * prozent / 100

gleiche Ergebnisse!

Kann mir jemand erklären, wieso mein Microsoft Visual C++ 2003-Compiler da einen Unterschied macht?
 
Jeder richtige C++-Compiler wird dir das so liefern:

In der oberen Zeile dividierst du zwei int-Werte. Dabei werden Nachkommastellen nicht berücksichtig. Auch eine automatische Umwandlung in float oder double findet nicht statt.

Du kannst eine Umwandlung erzwingen, indem du durch 100.0 dividierst (das erzwingt ein double-Ergebnis). Alternativ kannst du auch (double)prozent / 100 schreiben.
 
OK, das verstehe ich!

Worum es mir eigentlich geht, ist warum die beiden Schreibweisen:

1) power * (1.0 + prozent / 100)
2) power + power * prozent / 100

nicht das gleiche Ergebnis liefern!

Die 1. hatte ich zuerst in die Funktion "Kraft steigern" eingesetzt. Diese hat dann aber die beschriebenen falschen Resultate geliefert!
Erst als ich die 2. einsetzte, kamen korrekte Ergebnisse heraus! Hier wurde ja auch nichts durch eine Division mit 100.0 erzwungen und trotzdem war der Rückgabewert richtig.

Gruss, Rofi
 
Zuletzt bearbeitet:
Hi.

Punkt- geht vor Strich-Rechnung und die Auswertung von Ausdrücken geschieht von links nach rechts.

Im ersten Ausdruck muß demnach zuerst prozent / 100 berechnet werden. Das ist eine reine Integer-Operation - da die beiden Operanden Integer sind. Das Ergebnis ist wieder ein Integer. Der wird dann - bevor mit dem double Werte 1.0 multipliziert wird - implizit in einen double Wert umgerechnet. Erst zuletzt wird dann das Ergebnis des Klammerausdrucks mit dem Wert von power multipliziert.

Beim 2ten Ausdruck wird die Konvertierung des Integer Wertes der Variablen power schon früher erzwungen, da zuerst der Teilausdruck power * prozent berechnet werden muß. Dann wird mit dem (implizit in einen double Wert umgerechneten) Integer 100 multipliziert und zum Schluß noch die Addition ausgeführt.

Gruß
 
Code:
// Funktion Kraft steigern
int addProzent(int power, int prozent)
{
	return  (power * (1 +  prozent / 100));  // AUSDRUCK EINS
	//return (power + power * prozent / 100);  // AUSDRUCK ZWEI
}
@deepthroat
Irgendwie ist mir diese ".0" da reingerutscht, das war eigentlich nicht vorgesehen.
Jetzt gehe ich in Ausdruck 1 von rechts nach links vor:
Sagen wir power = 100. prozent = 15:
1) 15/100 = 0.15 ergibt also 0
2) 0+1 = 1 // innere Klammer zuerst
3) 1*100 = 100
BINGO! Jetzt hab ich's gerafft!

Bei Ausdruck 2 wäre es dann:
1) 15/100 = 0.15 ergibt also 0
2) 0*100 = 0
3) 0+100 = 100
:mad: :( Gar nicht's hab ich gerafft!
 
Zuletzt bearbeitet:
Hallo!
Probier mal bei Ausdruck zwei folgendes zu scheiben, dann sollte das gleiche rauskommen:

Code:
//return (power + power * (prozent / 100));


der Compiler rechnet wie gesagt von links nach rechts und würde erst Power mit Prozent multiplizieren und danach durch 100 teilen.
 
Rofi hat gesagt.:
Code:
return (power + power * prozent / 100);
Bei Ausdruck 2 wäre es dann:
1) 15/100 = 0.15 ergibt also 0
2) 0*100 = 0
3) 0+100 = 100
:mad: :( Gar nicht's hab ich gerafft!
Nein, bei Ausdruck zwei wäre es dann (da Multiplikation und Division die gleiche Priorität haben => beides Punkt-Rechnung) und von links nach rechts ausgewertet wird:

1) 100 * 15 == 1500
2) 1500 / 100 == 15
3) 100 + 15 == 115

Gruß
 
deepthroat hat gesagt.:
Nein, bei Ausdruck zwei wäre es dann (da Multiplikation und Division die gleiche Priorität haben => beides Punkt-Rechnung) und von links nach rechts ausgewertet wird:

1) 100 * 15 == 1500
2) 1500 / 100 == 15
3) 100 + 15 == 115

Gruß


genau deswegen müssen die zusätzlichen Klammern stehen! (siehe Beitrag oben)
 
andreas_gierisch hat gesagt.:
genau deswegen müssen die zusätzlichen Klammern stehen! (siehe Beitrag oben)
Nein, müssen sie nicht, denn er will ja das Ergebnis so haben wie es mit dem 2ten Ausdruck berechnet wird (siehe den 3. Beitrag) und vor allem wollte er verstehen warum es so ist - das man das mit Klammern hinbiegen kann wird ihm vermutlich selbst klar sein.

Gruß
 
Rofi hat gesagt.:
OK, das verstehe ich!

Worum es mir eigentlich geht, ist warum die beiden Schreibweisen:

1) power * (1.0 + prozent / 100)
2) power + power * prozent / 100

nicht das gleiche Ergebnis liefern!

Die 1. hatte ich zuerst in die Funktion "Kraft steigern" eingesetzt. Diese hat dann aber die beschriebenen falschen Resultate geliefert!
Erst als ich die 2. einsetzte, kamen korrekte Ergebnisse heraus! Hier wurde ja auch nichts durch eine Division mit 100.0 erzwungen und trotzdem war der Rückgabewert richtig.

Gruss, Rofi



ok, ich glaub jetzt hab ich das Problem richtig verstanden. Wie schon geschrieben, schneidet der Compiler bei der Division durch 100 den Nachkommateil ab. Deshalb kommt im ersten Fall für prozent / 100 gleich 0 raus (statt dem wahren Wert 0.15). Im zweiten Beispiel rechnet er erst 100 * 15 = 1500 und danach durch 100 und es kommt 15 raus, was auch korrekt ist. Der zweite Fall wird auch nur korrekt, solange beim Produkt aus power * prozent mindestens zwei Nullen am Ende sind, weil andernfalls der Nachkommateil abgeschnitten wird.

Das heißt du musst wirklich eine Typumwandlung erzwingen, um Fehler im Ergebnis zu vermeiden.
 
Zurück