C: Berechnung Summe negativer Zahlen?

5 Antworten

Die Schleifenbedingung ist i<=k. 0 ist aber nie kleiner als eine negative Zahl. Dass k negativ ist, stellst du sogar schon im if sicher. Entweder du lässt i rückwärts laufen (i--) oder du musst bei i=k starten.

Übrigens: Der Code ist optimierbar.

Desweiteren lässt sich die Summe von ungeraden Zahlen als Quadratzahlen schreiben.



Woher ich das weiß:Studium / Ausbildung – Mathematik
Suboptimierer  03.05.2019, 12:32

PPS: Was soll eigentlich n = n + 1 bewirken?

Vorschlag:

for(i=k; i<0; i++) 
  n+=i;
0
Suboptimierer  03.05.2019, 12:44
@Suboptimierer

Upps, du musst noch die geraden Zahlen heraus fischen:

for(i=k; i<0; i++) 
  if(i%2==1)
    n+=i

Oder Vorweg k auf die nächste ungerade Zahl stellen und dann mit 2 inkrementieren:

if(k%2==0)
  k++;
for(i=k; i<0; i+=2) 
  n+=i
1
MrAmazing2  03.05.2019, 18:01
@KarlRanseierIII

Natürlich klappt das. Was sollte daran nicht klappen? Modulo funktioniert bei negativen Zahlen genauso.

0
Suboptimierer  03.05.2019, 19:10
@KarlRanseierIII

Dann ist der Modulo schlecht programmiert worden in der Programmiersprache. Der Modulo liefert standardmäßig den kleinsten nichtnegativen Repräsentanten.

0
KarlRanseierIII  03.05.2019, 20:34
@Suboptimierer

Nö, es ist schlichtweg kein Modulo, sondern Remainder. Andere Funktion, andere Semantik.

Macht bei positiven Operanden keinen Unterschied. Python, Ruby, Perl implementieren ein mod bei % während C/C++, Java... den Remainder implementieren.

0
Suboptimierer  04.05.2019, 00:28
@KarlRanseierIII

Mit der Formel (a/b)*b +a%b =a stimmt etwas nicht. (a/b) * b lässt sich vereinfachen zu a.
a + a%b = a bedeutet, dass a%b = 0 ist. Das ist aber nicht allgemeingültig.

0
KarlRanseierIII  04.05.2019, 01:07
@Suboptimierer

/ ist dabei natürlich die Ganzzahldivision, mein Fehler.

(Also Beispiel 9/2 =4 (*2 =8), also liefert a%b=1, analog -7/2 = -3 ( *2= -6) entsprechend liefert hier a%b -1. Gelegentlich wird es auch als symmetrisches Modulo bezeichnet, nicht zu verwechseln mit dem Modulo, wie wir es in der Zahlentheorie kennen.

Letztlich liegt die Wurzel im Rechenwerk, C ist da recht nah an der Maschine. Wenn ich die Division als Folge von Subtraktionen (respektive Additionen) darstelle, zähle die Anzahl mit, bis der Remainder im Betrag zu klein geworden ist, erhalte ich das Ganzzahldivisionsergebnis und im Quellregister verbleibt dann der Remainder.

Viele ISAs haben dann eben auch die Operation, die gleich beides liefert. Und viele Programmiersprachen bieten diese Operation dann auch direkt an, wobei auch hier die Ergebnisse überraschen können. Python meint divmod (-7,2) ist (-4,1), C sagt div(-7,2) ist (-3,-1).

Und so kann man jede Menge Spaß haben, wenn man vorher nicht genau die Spezifikation durchliest :-/.

1
Suboptimierer  04.05.2019, 01:42
@KarlRanseierIII

C finde ich an dieser Stelle intuitiver als Pyhon. Wenn ich Remainder mit Rest übersetze, ist -7/2 = -3 Rest -1, da -7 = -3 * 2 + (-1) ist.

Auf das Ergebnis käme man auch mittels schriftlicher Division, die wir noch aus der Grundschule kennen.

Bei Python hingegen scheinen wir mit divmod wieder den richtigen Modulo zu haben, denn dort wird wieder der kleinste nichtnegative Repräsentant zurück gegeben.

1
KarlRanseierIII  04.05.2019, 02:04
@Suboptimierer

Japp, intuitiver ist der Remainder allemal im neg. Bereich, ganz klar.

Man muß halt nur wissen, daß eben % der Remainderoperator in der einen Sprache und das 'echte' Modulo in der anderen ist. Wenn man aber mit mehr als nur einer Sprache hantiert ist die unterschiedliche Nutzung (Mod/Remainder bzw. Residue) eine echt miese Stolpferfalle.

0

1) Es gibt keine if-Schleife. Es handelt sich um eine Struktur für eine Verzweigung. Sie liefert also einen funktionalen Unterschied zur Schleife.

2) Nimm den Backslash hinter Error raus. Andernfalls maskierst du das Anführungszeichen danach und der String wird nicht beendet.

3) Wieso deklarierst du i global? Es reicht, die Variable in dem Kontext anzuführen, in dem sie gebraucht wird. In deinem Fall wäre dies der else-Körper. Auch n muss wohl nicht global sein.

4) Gib n einen expliziten Startwert, bevor du die Variable verwendest. Vergib nach Möglichkeit immer explizite Startwerte vor einer Nutzung einer Variablen. Das reduziert Fehlerquellen.

5) Deine Schleife läuft so lange, wie die Bedingung i <= k erfüllt wird. Die Variable i hat den Startwert 0, die Variable k den Wert -8. Die Bedingung kann also nicht erfüllt werden, -8 ist kleiner als 0. Die Schleife läuft nicht, der Wert von n bleibt 0.

Wenn du nur die ungeraden negativen Zahlen haben willst, dann starte bei -1 und zähle einfach in Zweier-Schritten runter:

int sumfoo(const int k) {
	int result = 0;

	for (int i = -1; i >= k; i -= 2) {
		result += i;
	}

	return result;
}

Das erschlägt dir auch die Behandlung des Sonderfalls bei " >= 0", weil dann immer automatisch "0" zurück gegeben wird. Falls du allerdings wirklich eine Fehlermeldung ausgeben willst, weißt du ja schon, wie man das macht.

Außerdem solltest du die Variablen Funktionslokal deklarieren, und auf Globals verzichten. :)

LolekUndBolek  03.05.2019, 13:15

PS: Habe gerade noch eine wesentlich bessere Lösung mithilfe einer Abwandlung der Gauß'schen Summenformel gebaut. Damit lässt sich dein Problem völlig ohne Schleifen mithilfe von ein paar Grundrechenoperationen durchführen. Aber egal, das war ja nicht die Aufgabenstellung ... :)

1

Bevor du mit einer langweiligen FOR Schleife auf das Problem losgehst, solltest du es erst mal vom mathematischen Standpunkt aus etwas genauer betrachten.

So wie das der 11jährige Carl Friedrich Gauß im Jahre 1786 bereits tat:

https://de.wikipedia.org/wiki/Gau%C3%9Fsche_Summenformel#Verwandte_Summen

LolekUndBolek  03.05.2019, 16:28

Zwei Idioten, ein Gedanke. :)

Lies mal den Kommentar unter meiner Antwort! ;)

1

Vielleicht eher so:

int summe(int k){
  if (k>=0) return 0; /* Fehlerhafte Eingabe */
  int sum=0;
  for (int i=k;i<0;++i) if (i%2!=0) sum+=i;
  return sum;
}

Alternativ: Prüfe Anfangs ob k gerade ist, wenn nein, dann erhöhe um 1 und mache dann ein 2er Stepping in der Schleife.