PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Summen von x bis n bilden lassen


Gast
2009-06-27, 12:10:09
Hallo,

Ich muss was in javascript machen mit dem man die Summen von einer Zahl zbsp. 4 bis zu einer anderen Zahl zbsp 10 bilden lassen kann und das ganze dann in einem 3ten Textfeld ausgeben wird : also hier 4+5+6+7+8+9+10 = 49.


function chan()
{
var zahlx = document.getElementsByName("t")[0].value; // Eingabefeld 1 val
var zahln = document.getElementsByName("t")[1].value; // Eingabefeld 2 val
var i=zahlx;


while (i<=zahln)
{zahlx += parseInt(zahlx) + parseInt(i);
i++;}

document.getElementsByName("t")[2].value = zahlx;


so hab ichs mir gedacht funktioniert aber irgendwie nicht :/

tombman
2009-06-27, 12:21:26
Wie wärs mit Gausscher Summenformel? Einmal von 1 bis Anfang, dann von 1 bis Ende, dann 2.Ergebnis minus 1. Ergebnis ;)

Gast
2009-06-27, 12:25:36
Wie wärs mit Gausscher Summenformel? Einmal von 1 bis Anfang, dann von 1 bis Ende, dann 2.Ergebnis minus 1. Ergebnis ;)

Danke tombman für deine Hilfe, jedoch nicht das richtige, sorry

Gast
2009-06-27, 12:32:08
Thx, ich bin der TE aber gut wenn jemand anders antwortet :ugly: ich werds mal testen klingt logisch :>

Monger
2009-06-27, 12:34:37
JScript hab ich leider keine Erfahrung mit, aber kann es sein dass die Typen nicht stimmen?

zahlx und zahln sind doch vom Typ String, sonst würdest du später nicht parsen. i müsste ebenso vom selben Typus sein wie zahlx, schließlich machst du eine Zuweisung.

Dann prüfst du aber, ob i kleiner als zahln ist... sprich: du fragst zwei Strings, welcher von beiden kleiner ist. Das macht hier keinen Sinn.

Parse doch mal alle Werte schon direkt beim einlesen auf int. Sprich:

var zahlx = parseInt(document.getElementsByName("t")[0].value); // Eingabefeld 1 val
var zahln = parseInt(document.getElementsByName("t")[1].value); // Eingabefeld 2 val

instinct
2009-06-27, 12:41:12
Danke tombman für deine Hilfe, jedoch nicht das richtige, sorry

Würde ich schon sagen, wobei 1 bis Anfang nicht ganz richtig ist. Es muss 1 bis Anfang-1 heissen.

1-3: 6
1-10: 55

55-6 = 49

#44
2009-06-27, 12:59:58
zahlx += parseInt(zahlx) + parseInt(i);

so hab ichs mir gedacht funktioniert aber irgendwie nicht :/

Lass mich raten... es kommen zu hohe Zahlen raus?

Entweder += oder zahlx im rechten Term.


Und selbst dann addierst du die erste zahlx noch 2x hinein, i sei dank.
var i = parseInt(zahlx) + 1;
sollte dies beheben.

Ooooder du machst es gleich vernünftig, und missbrauchst zahlx nicht als Ergebnisvariable.

Und parseInt ist eig. nur nötig wenn du nicht sicher sein kannst, also beim User-Input. Nicht bei i und nach dem einlesen von zahlx/y

So z.B.:

function chan()
{
var zahlx = parseInt(document.getElementsByName("t")[0].value); // Eingabefeld 1 val
var zahln = parseInt(document.getElementsByName("t")[1].value); // Eingabefeld 2 val

var i = zahlx + 1;

while (i <= zahln)
{
zahlx += i;
i++;
}

document.getElementsByName("t")[2].value = zahlx;
}

Gast
2009-06-27, 15:46:31
http://www.abload.de/thumb/summecy5h.png (http://www.abload.de/image.php?img=summecy5h.png)

Leider kann ich kein javascript.

Gast
2009-06-27, 16:14:03
Lol wieder son nerd der nix zu tun hat und irgendnen fuck postet...


thx at #44 so gehts

#44
2009-06-27, 16:16:52
Noch n bissl besser als der Vorschlag von Tombman/Gast:

function chan()
{
var von = parseInt(document.getElementsByName("t")[0].value);
var bis = parseInt(document.getElementsByName("t")[1].value);

var result = 0.5 * (von + bis) * (bis - von + 1);

document.getElementsByName("t")[2].value = result;
}
Das Prinzip der gausschen Summenformel von 1-n auf m-n erweitert...

Braucht dann natürlich nicht annähernd soviel Rechenzeit wie die Schleife :)

Man sollte aber darauf achten das 0 < m <= n... Sonst läuft's bissl schief.

€: Hat diese Formel nen eigenen Namen?

Kinman
2009-06-27, 19:32:51
Lol wieder son nerd der nix zu tun hat und irgendnen fuck postet...


thx at #44 so gehts

Sollte das auf die handgeschriebene Formel bezogen, sein... Die ist (hab nur kurz drauf gesehen) korrekt.

Die Summe aller Zahlen bis n ist
(n² + n) / 2

Du willst sie Summe aller Zahlen von a bis b

= ((b² + b) / 2) - (((a-1)² + a - 1) / 2)

bsp. von a = 3 bis a = 5
3+4+5 = 12

((5² + 5) / 2) - (((3-1)² + 3 - 1) / 2) =
(30 / 2) - (6 / 2) = 12

Ob das schneller ist, als mit einer Schleife aufzuaddieren, ist fraglich

mfg Kinman

Berni
2009-06-27, 20:07:49
Wenn du nur 3 bis 5 addieren willst ists natürlich schneller wenn mans direkt macht. Bei sowas ist der Geschwindigkeitsunterschied aber auch kaum relevant. Aber schau dir mal an was passiert wenn du b=100000 setzt. Die Laufzeit ist eben bei der anderen Variante praktisch konstant (O(1)) während sie beim einfachen Addieren immer länger wird je größer der Unterschied zwischen a und b ist (O(n))!

Falls es performancetechnisch tatsächlich so relevant ist könnte man auch eine Fallunterscheidung machen und alles mit b-a < 10 per Schleife rechnen und den Rest eben mit der Formel.

#44
2009-06-27, 20:17:35
Ob das schneller ist, als mit einer Schleife aufzuaddieren, ist fraglich
Ich würde aus dem Bauch raus behaupten das man schon messbar schneller ist, bevor die Distanz der beiden Zahlen zweistellig wird.

2 Additionen 1 Vergleich und ein Sprung pro Schleifendurchlauf VS. 2 Additionen 1 Subtraktion und 2 Multiplikationen (siehe mein 2. Beispiel; Post #10).

Mit Firebug eben mal Profiling gemacht: Meine 2. Variante liegt schon vorn, wenn die Differenz der Werte nur 3 beträgt.

€: OK jetzt hab ich mal zu jeder Variante mit 100.000 Aufrufen Profiliert. Nur wenn die Differenz 0 ist gewinnt die Schleife nen Blumentopf :ulove: 552,087ms vs. 549,281ms

rotalever
2009-06-27, 20:33:14
Ich glaube kaum, dass es hier darum geht die letzten % Geschwindigkeit rauszuholen, sonst würde man es auch nicht mit JavaScript machen ;)

#44
2009-06-27, 20:40:18
Ich glaube kaum, dass es hier darum geht die letzten % Geschwindigkeit rauszuholen, sonst würde man es auch nicht mit JavaScript machen ;)

Natürlich, aber man muss ja große Differenzen erwarten, und selbst dann möchte man den Browser nicht zum Stillstand bringen ;)

Das Profiling hab ich aus reinem Interesse gemacht *g*

Neomi
2009-06-27, 20:43:53
Falls es performancetechnisch tatsächlich so relevant ist...

Die Schleifenvariante dürfte sich grundsätzlich nicht lohnen, aus diversen Gründen. Die direkte Formel kann man auch noch weiter zusammenkürzen:

(b - a + 1) * (a + b) / 2

Die Herleitung spare ich mir hier, die kann wohl jeder bei Bedarf selbst nachvollziehen. Die letzte Division ist in der Integerarithmetik durch einen Bitshift um 1 Bit ersetzbar, das ist viel billiger als eine teure Division. Es bleiben also zwei Additionen, eine Subtraktion, eine Multiplikation und ein Bitshift übrig. Die Multiplikation ist die einzige Operation dabei, die nicht bei allen modernen Architekturen billig ist.

Dagegen steht die Schleifenvariante. Es ist nicht nur eine Addition pro Schleife. Die Zählervariable muß in jedem Durchlauf um 1 inkrementiert werden, das ist schonmal eine Addition. Dann auf die bisherige Summe draufgerechnet, das ist die zweite Addition. Jeder Schleifendurchlauf erfordert dann auch noch einen Vergleich (ist auch nicht gratis) und einen bedingten Sprung (kann teuer werden, wenn die Sprungvorhersage nicht richtig rät).

Hauptsächlich wegen den bedingten Sprüngen in der Schleifenvariante sehe ich darin schon keinen Performancevorteil mehr, wenn b auch nur um 1 größer ist als a, bei einem Unterschied von 2 oder spätestens 3 würde ich von einem Nachteil ausgehen. Wenn dazu per "if (b - a < 10)" noch eine weitere Subtraktion, ein weiterer Vergleich und ein weiterer bedingter Sprung kommt, um diese Variante nur bei "passenden" Parametern auszuführen, dürfte sich jeder potentielle Vorteil gegenüber einer komplett sprungfreien Variante ohne vorherige Profung in Rauch auflösen.

Edit: hoppla, #44 war ja deutlich schneller. Hatte den Tab wohl zu lange im Hintergrund offen. Aber immerhin habe ich noch eine Multiplikation weniger. :D