Dezimal in 36er System Konverter 637

Für die Erstellung von einzigartigen vierstelligen Codes für den URL Shortener YOURLS habe ich nach einer Möglichkeit gesucht, möglichst viele verschiedene Codes mit nur vier Stellen zu erzeugen.

Nimmt man für jede Stelle eine Zahl von 0-9 hat man insgesamt 10.000 (10⁴ = 10 * 10 * 10 * 10) Möglichkeiten. Z.B.:

Würde man einen vierstelligen Code mit Hilfe des Alphabets erzeugen hätte man bereits 456.976 (26⁴ = 26 * 26 * 26 * 26) Möglichkeiten, da an jeder Stelle die Buchstaben von A-Z (=26) stehen könnten. Z.B.:

Will man noch mehr verschiedene Codes bekommen, kann man die Zahlen mit den Buchstaben verknüpfen, sodass man für jede Stelle 10 + 26 = 36 Möglichkeiten bekommt. Daraus ergeben sich 1.679.616 (36⁴ = 36 * 36 * 36 * 36) verschiedene Codes. Z.B.:

Die dritte Möglichkeit erzeugt für den Anfang genügend eindeutige Codes zur Nutzung von YOURLS. Da das Programm aber immer eine aktuelle ID als Code zurückgibt, müssen wir diese ID, die nur aus Zahlen besteht, in unser 36er System umwandeln.

Algorithmus

Zum Testen erstellen wir ein Programm in Python, welches eine beliebige Dezimalzahl (z.B.: 32245) in unser 36er System umwandelt:

import csv

#optional können die erstellten Codes in einer CSV Datei gespeichert werden
f = open('codes.csv', 'w', newline='')
writer = csv.writer(f)

#wandelt eine Zahl n in das 36er System (0-9 und A-Z) um 
def tenToThirtysix(n):
    #Array speichert den aktuellen Code, der 1-100 Stellen haben kann
    #wir benötigen eigentlich nur 4
    thirtysixVal = [''] * 100
    #ist die umzuwandelnde Zahl 0, schreiben wir diese direkt in den Array
    if(n==0):
        thirtysixVal[0] = "0"
        i = 1
    else:
        i = 0
    
    #Die umzuwandelnde Zahl wir solange zerlegt, bis die Zahl gleich 0 ist 
    while(n != 0):
        temp = 0
        temp = n % 36 #alle Zahlen und Buchstaben
        if(temp < 10):
            #die Funktion chr() findet die Zahl/den Buchstaben anhand des Unicodes
            #die +48 bzw. +55 ist nötig, da 
            thirtysixVal[i] = chr(temp + 48)
            i = i + 1
        else:
            thirtysixVal[i] = chr(temp + 55)
            i = i + 1
        n = int(n / 36)
            
    #Code wird aus dem Array ausgelesen
    newValue = ""
    j = 0
    while(j < i):
        newValue += thirtysixVal[j]    
        j = j + 1
    print(newValue)
    #writer.writerow([newValue])


#Funktion wird ausgeführt
tenToThirtysix(25) #ergibt: P
tenToThirtysix(1295) #ergibt: ZZ
tenToThirtysix(1250000) #ergibt: 8ISQ

f.close()

Im Code nutzen wir den Modulo % Rechenoperator, welcher den Rest einer ganzzahligen Division zurückgibt, um eine Zahl solange zu „zerlegen“ bis diese keinen Rest mehr zurück liefert. Der Rest, auch 0, wird dann mit Hilfe der „chr()“ Funktion in eine Zahl von 0-9 oder in einen Buchstaben von A-Z umgewandelt und in einem Array gespeichert.

16 % 16 = 0

17 % 16 = 1

150 % 70 = 10

Hier kannst du die Modulo-Rechenoperation selbst testen:

1. Zahl Modulo 2. Zahl Rest
%

 

Das Ergebnis ist super. Aus der großen Zahl 1,25 Million wird der Code 8ISQ.

In folgender ASCII Tabelle sieht man, welche Zahl oder welchen Buchstaben man bekommt, wenn man die „chr()“ Funktion nutzt. Zum Beispiel ergibt „chr(48)“ die Zahl 0 und „chr(65)“ den Buchstaben A:

Dez ASCII Dez ASCII
48 0 73 I
49 1 74 J
50 2 75 K
51 3 76 L
52 4 77 M
53 5 78 N
54 6 79 O
55 7 80 P
56 8 81 Q
57 9 82 R
65 A 83 S
66 B 84 T
67 C 85 U
68 D 86 V
69 E 87 W
70 F 88 X
71 G 89 Y
72 H 90 Z

Tests

Damit wir die Richtigkeit unserer Überlegungen überprüfen können und sehen, dass die Zahlen von 0 – 1.679.616 wirklich in vierstelligen Codes abgebildet werden, führen wir die erstellte Funktion innerhalb einer Zählwiederholung aus. Die Zählwiederholung kannst du dem Code von oben ganz am Ende hinzufügen. Wichtig ist noch, die Zeile „print(newValue)“ zu entfernen oder auszukommentieren, da sonst alle Zahlen in der Konsole ausgegeben werden, was sehr lange dauert:

    ...
    #Code wird aus dem Array ausgelesen
    newValue = ""
    j = 0
    while(j < i):
        newValue += thirtysixVal[j]    
        j = j + 1
    #print(newValue)
    writer.writerow([newValue])


#Funktion wird ausgeführt
for z in range (0, 1679617):
    tenToThirtysix(z)

f.close()

Ich habe die Anzahl der Zählwiederholungen um 1 über das errechnete Maximum gestellt, da dies dann der erste fünfstellige Code sein müsste. Hier das Ergebnis der erstellten CSV-Datei:

Unsere Überlegungen waren richtig.

Hier kannst du die CSV-Datei mit allen 1.679.616 Codes herunterladen:

Links

unsere-schule.org

×

Dezimal in 36er System Konverter

Code: 637