Rolf B: Zahlenreihe mit JavaScript bearbeiten

Beitrag lesen

Hallo skimann,

ich habe zwar eine Weile gesucht, den Luhn-Algorithmus aber nicht gefunden.

Dann ist ein Beispiel falsch - es sieht so aus als würde bei Luhn die Position 2,4,6,8,10 verdoppelt; du hast aber 1,3,5,7,9,11 verdoppelt. Das ist vom Programmieren her zwar egal, die Vorgehensweise ist die Gleiche, aber natürlich beeinflusst es ein paar Details.

Schauen wir mal was Du bisher gemacht hast:

x=document.Eingabe.nummer.value;  
var multi = 2;
var gesamt = 0;
for (var i = 0; i == 10; i++)
y = x.charAt(i);
y = parseInt(y);
y = y * multi;
    var summe = 0;  // ab hier Quersumme berechnen
        var segs = (y+'').split('');
        for (var a=0; a<segs.length; a++)
           summe += parseInt(segs[a]);    
gesamt = gesamt + summe;
if (multi == 2) {   // Multiplikator abwechselnd von 2 auf 1 setzen, bzw umgekehrt
multi = "1";
}
else {
multi = "2";
}

Folgende Hinweise hätte ich für Dich:

  • wenn Gunnar mit dem Luhn-Algurithmus recht hat, musst Du erst die zweite Stelle verdoppeln, nicht die erste. Du musst also mit multi=1 beginnen.

  • Du möchtest vermutlich in der for-i Schleife mehr tun als nur y = x.charAt(i);. Das ist eine Eigenschaft des for-Befehls: Er führt genau eine Anweisung aus. Wenn Du mehr als eine Anweisung in der Schleife haben willst, musst Du sie mit { ... } zu einem Block zusammenfassen. Dieser Block wird von for dann wieder wie eine Anweisung behandelt. In deinem if für multi hast Du es gemacht. Beim for musst Du sowas auch machen. Du musst Dir nur überlegen, welche Befehle alle in die Schleife hinein gehören.

  • Statt x.charAt(i) hättest Du auch x[i] schreiben können. Das tut das Gleiche.

  • Es ist zwar schwieriger lesbar, aber man muss nicht jede Operation einzeln durchführen. Statt

   y = x.charAt(i);
   y = parseInt(y);
   y = y * multi;

kann man auch schreiben

   y = parseInt(x[i]) * multi;

Wie wir schon anderswo schrieben, konvertiert der * Operator automatisch Strings in Zahlen, d.h. das parseInt könnte man auch weglassen, aber das würde ich persönlich nur beim Codegolfen tun, nicht in Code, den ich nachher noch verstehen will.

  • Wenn Du doch schon weißt, dass man mit charAt an die Zeichen einer Zeichenkette kommt, warum mühst Du Dich dann in der Quersumme mit split('') ab? Das ist doch unnötig kompliziert. Aber egal, weil...

  • Die Quersumme der mit 2 multiplizierten Stellen berechnet man ohnehin einfacher (steht auch im Wikipedia-Artikel zu Luhn, und ich mache das oben in meinem Code-Golf auch). Nicht immer ist das, was in der Vorgabe steht, auch der beste Weg beim Programmieren. Du weißt, dass Du folgendes machen sollst:

    1. nimm eine Ziffer
    2. verdoppele sie, sofern es eine gerade Position ist
    3. Das Ergebnis sei y. Die Stellen von y seien z (Zehner) und e (Einer), d.h. y == 10*z + e.
    4. Ist y einstellig gewesen, dann ist z = 0.
    5. Addiere z+e auf die Gesamtsumme auf.

Du hast in y also 10z+e stehen, möchtest für y>9 aber eigentlich z+e haben. Der Unterschied zwischen 10z+e und z+e ist, wenn man sich an die Schulalgebra erinnert, 9z. Der Wert von z ist bekannt, nämlich 1, weil Du beim Verdoppeln niemals über die 18 hinauskommst. Du weißt also: Ist y>9, habe ich 9 zuviel. Statt Ziffern zu addieren, kannst Du in deinem konkreten Fall einfach 9 von y abziehen.

  • Auf den Umstand, dass Du multi nicht auf einen String-Wert, sondern auf einen Zahlenwert setzen müsstest, hat Dich Kalk schon hingewiesen. Das ist allerdings nicht ganz so dramatisch, weil JavaScript bei einer Multiplikation weiß, dass es Zahlen braucht, und Strings automatisch in Zahlen konvertiert. Bei einer Addition wäre das anders, weil die "Addition" von Strings zu einer Verkettung führt. "2" * "3" ergibt 6 (Zahl), "2" + "3" aber "23" (String). Das vergessen wir jetzt aber gleich wieder, weil...

  • Wenn man einen Schalter braucht, der zwischen zwei Werten wechselt, dann kann man die Abfrage einfacher formulieren, dafür gibt es den „Dreifach-Operator“ (engl. ternary operator). Der sieht so aus: bedingung ? wert1 : wert2. Ist die Bedingung wahr, liefert er wert1, ist sie falsch, liefert er wert2. In deinem Fall könnte man also schreiben:

   multi = multi == 1 ? 2 : 1;

Ich selbst bin da gelegentlich noch radikaler. Weil 1+2 == 3 gilt, schaltet

   multi = 3 - multi;

ebenfalls zwischen 1 und 2 hin und her, sofern multi korrekt auf 1 oder 2 initialisiert wurde. Aber wie dedlfix unten schreibt: Da behandle ich ein logisches Problem mit arithmetischen Mitteln und das ist unsauber.

  • Die Alternative zu einem Schalter ist die Berechnung des Multiplikationsfaktors mit Hilfe des %-Operators (Divisionsrest). i % 2 liefert für i=0,1,2,3,... die Werte 0,1,0,1,... Da addierst Du noch 1 drauf, und hast 1,2,1,2..., was genau die Multiplikationswerte sind, die Du brauchst. Der Einwand von dedlfix gilt natürlich auch hier.

Versuche mal, diese Hinweise bei Dir einzubauen. Ich möchte Dir nicht einfach eine fertige Funktion hinschreiben, aus Selbstmachen lernt man mehr. Es sei denn, du verwendest meine Codegolf-Zeile 😂

Editiert 13:56: Dedlfix' Hinweis bezüglich ?: Operator eingearbeitet

Rolf

--
sumpsi - posui - clusi