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?
> 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
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 ;)
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.
Jim M. schrieb:> Ein Programmierer sollte gut genug in Mathe sein um das sofort zu sehen.
Aber auch gut genug, um zu sehen dass es im Grenzbereich (n*(n+1) >
INT_MAX) zu unterschiedlichen Ergebnissen kommt.
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
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 ?
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.
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...
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 :)
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
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))return0;
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
intsumme(intn)// ich bin immernoch für unsigned!
2
{
3
if(n<1)returnn;// Vollbremsung
4
5
intmxroot=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
return0;// 0 zurückgeben
9
10
if(n>(INT_MAX-n)/n)// 2xSumme(n) ist grösser als INT_MAX
11
{
12
intret=(mxroot*mxroot+mxroot)/2;// auch dieser Wert ist eine Konstante eigentlich
13
for(;n>mxroot;n--)
14
ret+=n;
15
returnret;
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
intsumme(intn)
2
{
3
if((n<1)||(n>14142*sqrt(INT_MAX)/10000))
4
return0;
5
6
longret=n*n+n;
7
return(int)ret/2;
8
}
scheint mir schöner zu lesen und ist vermutlich auch schneller ;)
'sid
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.