C++ - ergebnis + 1/2 => Ausgabe ist 0, wieso?

Baker

Mitglied
Hallo,

folgender Code:

C++:
int main(void) {

    int eingabe;
    double ergebnis = 0;
    int x = 0;
    
    printf("Geben Sie eine Zahl ein: ");
    scanf("%d", &eingabe);
    
        for (int i = 1; i < eingabe; i++) {

            ergebnis = ergebnis + 1/(2+x);
            x = x + 2;
        
        }
    
    printf("%lf", ergebnis);
    
}

Das Programm soll eine Eingabe einlesen, z.B. 5 und dann am Ende folgendes Ergebnis ausgeben:

1/2 + 1/4 + 1/6 ... + 1/2*eingabe

aber wenn ich das so aufschreibe und z.B. plus 0.5 mache dann gibt er was aus, aber plus 1/2 gibt er immer 0 aus. Worin liegt hier das Problem?
 
K

kneitzel

Gast
x ist ein int - was für Werte kann ein int denn speichern? Was macht denn C/C++, wenn Du eine Fließkommazahl dazu addierst?
 
Beste Antwort

M.L.

Top Contributor
Zusätzlich scheint eine kleine Datentyp-Anpassung im Programm eher die gewünschten Resultate zu liefern:
C:
#include <stdio.h>
int main() {
  //std::cout << "Hello World!\n";
int eingabe;
    double ergebnis = 0.0;
    double x = 0.0;
    printf("Geben Sie eine Zahl ein: ");
    scanf("%d", &eingabe);
            for (int i = 1; i < eingabe; i++) {
    ergebnis = ergebnis + 1/(2+x);
            x = x + 2.0;
            }
        printf("%lf", ergebnis);
}
Code:
Geben Sie eine Zahl ein: 3
0.750000
 
K

kneitzel

Gast
Wobei ich gerade schaue - wurde der erste Code angepasst? Oder hatte ich Tomaten auf den Augen, hab Unsinn geschrieben und der TE hat daraus dennoch was brauchbares für sich heraus gelesen? (Letzteres vermute ich)

Da x immer um 2 erhöht wird kann das natürlich ein int bleiben. Das Problem ist halt nur, dass 1 / (2+x) alles Integer sind und daher findet da nur eine Integer Operation statt.

Damit der Compiler daraus keine Integer Division macht, würde dann ausreichen, dass man da Gleitkomma-Zahlen als Literale vorgibt, also sowas wie 1.0/(2+x) oder so. Dann wird klar, dass hier eine Fließkomma-Operation stattfinden soll. Das erreicht man natürlich auch, indem man x zu einem double macht, aber der nahe liegende Schritt wäre aus meiner Sicht tatsächlich das 1.0 / ... statt dem 1 / ....

Eine Optimierung, die ich machen würde, wäre dann aber noch: Auf i würde ich verzichten. In der for Schleife würde x bis 2*Eingabe laufen lassen und dabei x immer um 2 erhöhen. Das wäre dann unter dem Strich etwas wie:
C++:
  for (int x = 2; x <= eingabe * 2; x=x+2)
    ergebnis = ergebnis + 1.0/x;
 

Jw456

Top Contributor
Wobei ich gerade schaue - wurde der erste Code angepasst? Oder hatte ich Tomaten auf den Augen, hab Unsinn geschrieben und der TE hat daraus dennoch was brauchbares für sich heraus gelesen? (Letzteres vermute ich)

Da x immer um 2 erhöht wird kann das natürlich ein int bleiben. Das Problem ist halt nur, dass 1 / (2+x) alles Integer sind und daher findet da nur eine Integer Operation statt.

Damit der Compiler daraus keine Integer Division macht, würde dann ausreichen, dass man da Gleitkomma-Zahlen als Literale vorgibt, also sowas wie 1.0/(2+x) oder so. Dann wird klar, dass hier eine Fließkomma-Operation stattfinden soll. Das erreicht man natürlich auch, indem man x zu einem double macht, aber der nahe liegende Schritt wäre aus meiner Sicht tatsächlich das 1.0 / ... statt dem 1 / ....

Eine Optimierung, die ich machen würde, wäre dann aber noch: Auf i würde ich verzichten. In der for Schleife würde x bis 2*Eingabe laufen lassen und dabei x immer um 2 erhöhen. Das wäre dann unter dem Strich etwas wie:
C++:
  for (int x = 2; x <= eingabe * 2; x=x+2)
    ergebnis = ergebnis + 1.0/x;
Der Code wurde nicht verändert von TE.


ergebnis = ergebnis + 1/(2+x);
x = x + 2;
Laut der Aussage des TE will er 1/2 1/4 addieren.

Tut er aber nicht sondern 1/3 dann 1/4
In der Klammer soll es bestimmt ein "*" sein.
Somit würde bei der for Schleife 1:2*1 = 1/2
1:2*2 =1/4
1:2*3 =1/6
1:2*4 =1/8

Entstehen was er ja auch will
Also das Plus ist falsch nicht das int
Und das x=x+2 macht bei dem was er will auch keinen sinn.
 
K

kneitzel

Gast
@Jw456 Da liegst Du schlicht falsch. Das Problem in dem Code ist in erster Linie, dass die Division eine Division von Integern ist.

Und sowohl das 2+x als auch das x=x+2 sind in der Kombination richtig.

x von einem int zu einem double zu machen löst das Problem (daher auch die Markierung als Lösung nehme ich an, denn der TE wird das ja entsprechend umgesetzt haben). Aber die Lösung, einfach entsprechend passende Literale zu verwenden ist deutlich besser, denn Datentypen von Variablen sollten immer passend bleiben - und das ist hier ein int, da ja nur ganze, positive Zahlen in x gespeichert werden.
 
K

kneitzel

Gast
Dann muss er 1.0/(2.0+x) machen
Es reicht, an einer Stelle das .0 anzufügen. Also ein 1.0 / (2+x) - dann kann man auch problemlos ein Refactoring machen:
- Man könnte die Reihenfolge tauschen: Erst x um 2 erhöhen und dann die Rechnung durchführen (dann entfällt das "2+")
- Man könnte x am Anfang mit 2 initialisieren

Das nur als kleine 08/15 Veränderungen.
 

Jw456

Top Contributor
Es reicht, an einer Stelle das .0 anzufügen. Also ein 1.0 / (2+x) - dann kann man auch problemlos ein Refactoring machen:
- Man könnte die Reihenfolge tauschen: Erst x um 2 erhöhen und dann die Rechnung durchführen (dann entfällt das "2+")
- Man könnte x am Anfang mit 2 initialisieren

Das nur als kleine 08/15 Veränderungen.
Du kannst scheinbar auch nicht loslassen :):);)
 
K

kneitzel

Gast
Was hier wichtig ist, ist doch die Operator precedence:

Daher wird die Addition immer am Ende ausgeführt. Dein Link sagt übrigens auch nichts anderes aus - ist aber deutlich ungenauer und behandelt nur wenig Operatoren und beschränkt sich auf Aussagen wie Punkt vor Strich Rechnung.
 

Neue Themen


Oben