Formaler Parameter = globale variable oder = "Platzhalter?

Gast #6255604
Definiere Funktion
1
int summe (int n)

Dann folgendes:
1
int summe (int n) //Funktionskopf
2
{
3
int i;
4
int zwsumme = 0;
5
for (i = 1; i <= n; i = i + 1) //Funktionsrumpf
6
zwsumme = zwsumme + i;
7
return zwsumme;
8
}
der Wert von zwsumme wird durch return an int n weitergeben?
1
resultat = summe (eingabe);
eingabe ist der aktuelle Parameter bzw. das Argument der
Funktion summe().

Warum geht man den Umweg über int n, wenn man doch dann einen anderen 
parameter nutzt? Dient int n als Platzhalter und die aktuelle Variable 
kann dadurch variieren?
Gast #6255610
> Warum geht man den Umweg über int n, wenn man doch dann einen anderen
> parameter nutzt? Dient int n als Platzhalter und die aktuelle Variable
> kann dadurch variieren?

Was meinst du mit Umweg?, n ist einfach ein Parameter der Funktion und 
das Ergebnis ist ein voellig anderer Wert - formuliere deine Frage bitte 
anders
Gast #6255618
Nee, das hast Du nicht richtig interpretiert.
1
int summe (int n);

In diesem Prototyp erklärst Du dem Compiler, dass es eine Funktion gibt, 
die

1) einen 'int' als Wert zurückgibt
2) "summe" heisst
3) einen integer (n) als Parameter hat

Wobei der Name des PArameters (n) hier gar keine Rolle spielt. Es reicht
1
int summe(int);

Dein späterer Funktionsaufruf wäre also:
1
int ergebnis = summe(20);


Und in der Funktion, die Du daoben geschrieben hast, würde der wert 20 
nun
im Aktualparameter (int n) entgegengenommen und steht so innerhalb der 
Funktion als Variable zur Verfügung.

In der for-Schleife verwendest Du ihn dann ja auch um 'n' mal die 
Variable zwsumme zu inkrementieren.

zwsumme hat dann hinterher den gleichen Wert wie n... und wird zum 
Schluss per return() zurückgegeben.

Die Funktion macht so natürlich wenig Sinn.

Aber Du kannst ja mal Deine for-Schleife etwas abändern und zwsumme in 
jedem Durchlauf nicht um 1, sondern um 5 erhöhen.
1
int i = 0;
2
int zwsumme = 0;
3
for(i = 0; i<n; i++) {
4
  zwsumme = zwsumme + 5;
5
}

Dann unterscheiden sich auch ergebnis und Parameter ;)
#6255637
Der Lernende schrieb:
> verdammt, ich hatte das nichtb gesehen. Also n bestimmt die Anzahl der
> Durchläufe

Der Code im OP ist ein verdammt schlechtes Beispiel, denn die Summer 
1..n ist offensichtlich gleich n*(n+1)/2 (gaußsche Summenformel).

Ein Programmierer sollte gut genug in Mathe sein um das sofort zu sehen.

Die Schleife bräuchte man wenn man z.B. die ersten n Elemente eines 
Arrays aufsummieren möchte.
Gast #6255957
Dirk B. schrieb:
> Aber auch gut genug, um zu sehen dass es im Grenzbereich (n*(n+1) >
> INT_MAX) zu unterschiedlichen Ergebnissen kommt.

Während ich Dir da recht geben wollte;
hat Jim aber dennoch Recht was die Unsinnigkeit der Schleife angeht..

sollte n²+n > INT_MAX
kann man das Ergebniss noch immer Retten;
und sollte (n²+n)/2> INT_MAX ist eh alles verloren (naja ebenfalls 
rettbar aber eben nichtmehr mit der Funktion mit deklarierter 
int-Rückgabe.

Nun reicht also eine Vorab-Prüfung ob n nur halbsoviele bits hat wie 
INT_MAX
für eine 32bit uint also 65535 oder kleiner
( 65535²+65535 erzeugt nur 1111 1111 1111 1111 0000 0000 0000 0000 
schön, oder?)
und das Muster ist immer dasselbe egal ob man 8,16,32,64 oder welchen 
zweier-exponenten man auch immer nutzt.
das wär also schonmal leicht.

Grenzfälle (2^(log2(INT_MAX)/2)< n < 2^((log2(INT_MAX)/2)+1))
sind ebenfalls leicht an den bits abzuzählen
können aber direkt einfach vermieden werden indem man der Hilfsvariable 
ein ulong verpasst, gell ;)
(Son Tee am mittag kann ganz schön beruhigend sein ;))

Insofern:
Ich bin da ganz auf Jim's Seite

'sid
#6256004
sid schrieb:
> sollte n²+n > INT_MAX
> kann man das Ergebniss noch immer Retten;

Richtig. Aber wenn man es nicht bedenkt, verhalten sich die Funktionen 
unterschiedlich.

> und sollte (n²+n)/2> INT_MAX ist eh alles verloren

Dafür steht dann in der Referenz zur Funktion das maximale n drin, bzw 
es wird ein Fehler gesetzt.

Das ist halt Programmiererwissen. Sonst könnte das ja jeder ?
#6256051
Der Lernende schrieb:
> der Wert von zwsumme wird durch return an int n weitergeben?

So ganz verstehe ich nicht, was du damit sagen willst. n hat mit dem 
return oder mit zwsumme nichts zu tun.

> resultat = summe (eingabe);
> eingabe ist der aktuelle Parameter bzw. das Argument der
> Funktion summe().

Ja.

> Warum geht man den Umweg über int n, wenn man doch dann einen anderen
> parameter nutzt?

Welchen anderen? Es gibt nur n. Und was meinst du mit "Umweg"? Ich sehe 
hier keinen Umweg.

> Dient int n als Platzhalter und die aktuelle Variable kann dadurch variieren?

in n ist der Parameter. Das Argument, das du beim Aufruf übergibst, wird 
dort hinein kopiert. Innerhalb der Funktion lässt sich n wie eine 
gewöhnliche lokale Variable verwenden.
Gast #6256135
Der Stack in modernen Programiersprachen, wie z.B. C, ist ein echter 
Luxus. In, z.B. fortran, gab es das früher nicht. Heute kann man das 
dort mittlerweile wohl angeben, wenn den bei ner Funktion braucht. Und 
das ist nicht die einzige solche Sprache, mit der ich schon das 
Vergnügen hatte. Bei denen verhalten sich die Variablen meistens 
tatsächlich ein bisschen wie globale variablen, was dann echt lustig 
wird, wenn man mal ne Rekursion bräuchte...
Moderator #6256195
DPA schrieb:
> Der Stack in modernen Programiersprachen, wie z.B. C, ist ein echter
> Luxus. In, z.B. fortran, gab es das früher nicht.

Dafür hatte man in klassischen Fortran- und auch Cobol-Implementationen
den Luxus, keine Stack-Overflows befürchten zu müssen :)
Gast #6256376
Dirk B. schrieb:
> Dafür steht dann in der Referenz zur Funktion das maximale n drin, bzw
> es wird ein Fehler gesetzt.
>
> Das ist halt Programmiererwissen.

Naja wenn Du jetzt Einschränkungen für n definierst, dann ist Dein 
erster Einwand auch überflüssig, denn diese (bei zugegeben kleineren n) 
hätten das Problem ja auch gelöst nicht wahr? ;)

Oder willst DU mir weissmachen Du hast das Programmiereerwissen erst in 
den letzten paar Stunden erlangt? Na eben.

'sid
Gast #6257286
Dirk B. schrieb:
> sid schrieb:
>> denn diese (bei zugegeben kleineren n)
>> hätten das Problem ja auch gelöst nicht wahr? ;)
>
> klar, aber ein höheres n ist doch besser.

Nuja, aber dann reden wir schnell von BigInt libraries;

denn wie gesagt, ne long Krücke danebengestellt nutzt ja die volle 
int-Breite aus und kostet den Programmierer ein müdes Lächeln um solche 
Fehler zu umgehen.

Ne simple Abfrage vor dem berechnen kann auch n rudimentären "Fehler"
ausgeben .. q&d sowas wie
1
if ((n > 0) && (n > (INT_MAX-n) /n)) return 0;
wenn man long nicht mag
oder man zweigt dann ab,
berechnet die Summe für n^(log2(INT_MAX)/2)
(ist ja konstant bei bekanntem INT_MAX zum glück.. man 'merkt' sie sich 
einfach)
und fängt an der Stelle an zu addieren
also bei i=sqrt(INT_MAX)
(wieso auch immer man son blödsinn machen wollte)
spart man sich immernoch ne gaaanze Menge an Rechenezeit

die grenze von n ist ja immer 14142 * sqrt(INT_MAX) /10000
(int approx für Wurzel Zwei mal wurzel int_max)
das weiss man ja auch schon vorher (wenn man in Mathe aufgepasst hat)

Oder kurz.. im Grunde wär ich dann für etwas wie
1
int summe (int n) // ich bin immernoch für unsigned!
2
{
3
  if(n < 1) return n; // Vollbremsung
4

5
  int mxroot = sqrt(INT_MAX); // sollte man als Konstante definieren  falls man die funktion öfter aufruft mMn
6

7
  if (n > 14142 * mxroot /10000) // Summe(n) ist grösser als INT_MAX
8
    return 0;    // 0 zurückgeben
9
  
10
  if (n > (INT_MAX-n)/n) // 2xSumme(n) ist grösser als INT_MAX
11
  {
12
    int ret = (mxroot*mxroot+mxroot)/2; // auch dieser Wert ist eine Konstante eigentlich
13
    for (; n>mxroot; n--)
14
      ret += n;
15
    return ret;
16

17
    /* mMn besser:
18
    long ret = n*n+n;
19
    return (int) ret/2;
20
    */
21
  }
22
  return (n*n+n)/2; // schnell und problemlos
23
}

nur so als skizzierte Richtung...
denn ernsthafterweise ist mir n pauschales long lieb was das angeht..
das säh dann so aus:
1
int summe (int n)
2
{
3
  if ((n < 1) || (n > 14142 * sqrt(INT_MAX) /10000))
4
    return 0;
5

6
  long ret = n*n+n;
7
  return (int)ret/2;
8
}
scheint mir schöner zu lesen und ist vermutlich auch schneller ;)

'sid

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 6 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.