Sehr geehrter Herr Schnoor,

hier einige Fragen zu Ihrer Codepage-Methode und dem ominösen Zahlensystem zur 
Basis 4096.

Frage 1
Warum wählten Sie die Basis b = 4096 für Ihre Codepage-Methode (CPM) zum 
Nummerieren der UTF8-Zeichen?
Antwort: Da Sie bis jetzt diese Frage nicht beantwortet haben, hier ein 
Antwortversuch von mir.

Frage 2
Was ist Zweck oder Ziel der CPM? Wozu das Monster-Zahlensystem 4096?
Antwort: Sie wollen mit CPM den Speicherbedarf (gemessen in 8-Bit-Byte) für die 
dezimalen „Hausnummern“ ord(ch) der UTF8-Zeichen ch reduzieren, und zwar auf 
knapp die Hälfte, durch Verwendung der 4096-Index-Nummern, in die die dezimalen 
Hausnummern übersetzt werden. Die sind gewissermaßen getunte Hex-Zahlen (statt 
der Basis 16 die Superbasis 4096).

Und wozu dieser Aufwand? 
Die byte-reduzierten Hausnummern werden anstelle von Klartextnachrichten übers 
Netz verschickt. 
CPM ist im Kern eine Symmetrische Chiffre mit dem System-Ziffernstring als 
Schlüssel.


Frage 3
(damit man sieht, wo man anfängt, wo’s langgeht, und wo man endet):
Wie groß muß die Basis b>1 eines Zahlensystems sein, wenn man mit höchstens 2 
Ziffern dieses Systems genau 256 Zahlen (0..255) notieren können will.
Antwort: b = 16 = Wurzel aus 256, System = Hex-Zahlen
Denn mit 16 verschiedenen Ziffern kann man 16**2 = 256 ein- oder zweiziffrige 
Hex-Zahlzeichen notieren.

Was einmal geht, geht auch zweimal. Dachten Sie wohl. 
Und ich auch. 

Darum hier die zu Frage 3 analoge

Frage 4
Welche (minimale) System-Basis b>1 braucht man zum Nummerieren der aktuell 
1.114.111 UTF8-Zeichen, wenn man zum Nummerieren höchstens 2-ziffrige 
Zahlzeichen verwenden will?
Antwort: b = 1056 = gerundete Wurzel aus 1.114.111.

Überraschung Eins:
Die Antwort hat mich überrascht: Optimale Basis = wenig größer als ein Viertel 
der Superzahl.

==============================
Da Ihre CPM für alle Basiswerte  2 <= b <= 4098  anwendbar ist, habe ich den 
Rechner zur Basis-Testung angeworfen. 
Und die jeweilige Byte-Reduktion ermittelt.

Welchen Ziffernstring habe ich verwendet?
Den einfachsten: Alle UTF8-Zeichen von 0 bis zur jeweiligen Basis b. 

ziffern = ''.join([ chr(x) for x in range(0, 4096) ])
Anzahl Ziffern :   4096
Anzahl Bytes   :  10112

Dieser Ziffernstring ist optimal, denn der enthält die Zeichen mit den 
wenigsten Byte. Es gibt keinen Ziffernstring mit weniger Byte.

Die Basis läßt sich beliebige verkleinern durch Slicing, z.B.
basis = 128
ziffern = ziffern[:basis]

==========================

Überraschung Zwei:
Der Test lieferte eine merkwürdiges Ergebnis:

Die größte Byte-Reduktion über alle Codepoints 1 bis 1.114.111 liefert eine 
dreistellige Basis, b = 128.

Hier das Testergebnis für b = 128:

Basis für CPM : 128
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]    # ANZAHL der UTF8-Zeichen 
mit 0,1,2,3,4,5 Byte
BytesIndex    : [0, 128, 16256, 1095680, 0]    # ANZAH der Index-Zahlzeichen 
mit 0,1,2,3,4 Byte
ZiffernIndex  : [0, 128, 16256, 1095680, 0]    # ANZAH der Index-Zahlzeichen 
mit 0,1,2,3,4 Ziffern
Σ Bytes UTF8  : 4382592  # Gesamtzahl der Bytes in allen 1.114.111 UTF8-Zeichen
Σ Bytes Index : 3319680  # Gesamtzahl der Bytes in allen 
1.114.111Index-Zahlzeichen
Diff  (I - U) : -1062912  # klar
Quote (I : U) : 75.75%  # klar
Reduktion     : -24.25%  # klar

Ergebnis in Worten für b=128:
ZiffernIndex: Es werden nur 1-, 2-  oder 3-ziffrige Zahlzeichen verwendet;
BytesIndex: Diese Zeichen haben 1, 2, oder 3 Byte.
Die Anzahl der Zahlzeichen ist gleich der Anzahl der Byte.
Dies ist vollkommen logisch. Denn die Basis b=128 verwendet in dem 
MINIMALISTISCHEN Ziffernstring exakt 128 Zeichen von einem Byte.

Noch einen Tick besser ist die Byte-Reduktion für  b=129:

Basis für CPM : 129
BytesUTF8     : [0, 127, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 128, 16512, 1095423, 0]
ZiffernIndex  : [0, 128, 16512, 1095423, 0]
Σ Bytes UTF8  : 4382591
Σ Bytes Index : 3319421
Diff  (I - U) : -1063170    <== MIN -1.063.170
Quote (I : U) : 75.74%

==================================

Und hier der Test für ausgewählte Basis-Werte (b = 2**k, für k= 12, 11, …, 16)

Hinweis: 
Ist ein Reduktionswert POSITIV, handelt es sich tatsächlich nicht um eine 
Reduktion, sondern um einen Mehraufwand.
Nur NEGATIVE Reduktionswerte bedeuten tatsächlich weniger Aufwand.
Dies wird auch klar durch Quote (I : U)  = Quote (Index : UTF8)


Basis für CPM : 4096
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 129, 18432, 266253, 534529, 292721, 0]
ZiffernIndex  : [0, 4096, 1107968, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4437473
Diff  (I - U) : 54881
Quote (I : U) : 101.25%
Reduktion     : 1.25%

Basis für CPM : 2048
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 129, 18302, 297248, 796385, 0]
ZiffernIndex  : [0, 2048, 1110016, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4114017
Diff  (I - U) : -268575
Quote (I : U) : 93.87%
Reduktion     : -6.13%

Basis für CPM : 1024
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 129, 17149, 236481, 858305, 0]
ZiffernIndex  : [0, 1024, 1045504, 65536, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4177090
Diff  (I - U) : -205502
Quote (I : U) : 95.31%
Reduktion     : -4.69%

Basis für CPM : 512
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 129, 16379, 163334, 492155, 440067, 0]
ZiffernIndex  : [0, 512, 259584, 851968, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4691844
Diff  (I - U) : 309252
Quote (I : U) : 107.06%
Reduktion     : 7.06%

Basis für CPM : 256
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 129, 16639, 297863, 539369, 258064, 0]
ZiffernIndex  : [0, 256, 63232, 1048576, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4374792
Diff  (I - U) : -7800
Quote (I : U) : 99.82%
Reduktion     : -0.18%

Basis für CPM : 128
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 128, 16256, 1095680, 0]
ZiffernIndex  : [0, 128, 16256, 1095680, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 3319680
Diff  (I - U) : -1062912
Quote (I : U) : 75.75%
Reduktion     : -24.25%

Basis für CPM : 64
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 64, 4032, 256000, 851968, 0]
ZiffernIndex  : [0, 64, 4032, 256000, 851968, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4184000
Diff  (I - U) : -198592
Quote (I : U) : 95.47%
Reduktion     : -4.53%

Basis für CPM : 32
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 32, 992, 31744, 1013760, 65536, 0]
ZiffernIndex  : [0, 32, 992, 31744, 1013760, 65536, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 4479968
Diff  (I - U) : 97376
Quote (I : U) : 102.22%
Reduktion     : 2.22%

Basis für CPM : 16
BytesUTF8     : [0, 128, 1920, 61440, 1048576, 0]
BytesIndex    : [0, 16, 240, 3840, 59392, 983040, 65536, 0]
ZiffernIndex  : [0, 16, 240, 3840, 59392, 983040, 65536, 0]
Σ Bytes UTF8  : 4382592
Σ Bytes Index : 5558000
Diff  (I - U) : 1175408
Quote (I : U) : 126.82%
Reduktion     : 26.82%

Aber vielleicht sind das alles ja nur wilde Spekulationen? 

Wolfgang Büchel

=======================

Das verwendete Python-Programm:

ziffern = ''.join([ chr(x) for x in range(0, 4097) ])
for k in range(12, 3, -1):
    basis = 2**k
    countBytes_UTF8_CPM(basis, ziffern)

===============================

def countBytes_UTF8_CPM(basis, ziffern, zeigen=False):
    """
    Ermittelt die Gesamtzahl der 8-Bit-Bytes
    --  aller UTF8-Zeichen <ch> von 1 bis Max_UTF8 = 1.114.111
    --  aller aus <ch> via ord(ch) berechneten Indexzahlzeichen  
        für den Ziffernstring <ziffern>  der Länge <basis> nach CPM
        (sowie deren Ziffernanzahl)
        und  vergleicht diese beiden Byte-Anzahlen.
    
    """
    Max_UTF8 = 1114111
    ziffern = ziffern[:basis]   # Ziffernstring für Positionssystem CPM 
    basis = len(ziffern)        # Basis dieses Positionssystems
    print("\nBasis für CPM : %s" % basis)
    
    # Zähler für die ANZAHL der Bytes ...
    cnt_UTF8        = [0] * 6            # ... in UTF8-Zeichen ch
    cnt_Index_Bytes = [0] * 25    # ... in Index-Zahlzeichen <index>
                            # cnt_UTF8[i]   = ANZAHL der UTF8-Zeichen  mit i 
Byte
                            # cnt_Index8[i] = ANZAHL der index-Zeichen mit i 
Byte
    # BytesUTF8 : [0, 127, 1920, 61440, 1048576, 0] bedeutet:
    # UTF8 hat   0   0-Byte-Zeichen, 
    #          127   1-Byte-Zeichen, 
    #         1920   2-Byte-Zeichen, etc.
    
    # Zähler für die ANZAHL der Ziffern in Index-Zahlzeichen <index>
    cnt_Index_Ziffern = [0] * 25
    # cnt_Index_Ziffern : [0, 1023, 1045504, 65536] 
    # bedeutet:
    # Index hat    1023   1-Ziffern-Zahlzeichen
    #           1045504   2-Ziffern-Zahlzeichen
    #             65536   3-Ziffern-Zahlzeichen, etc.
    
    for i in range(1, 1 + Max_UTF8):
        # SKIP 2048 surrogates-Zeichen; 
        # in diesem Teilbereich liegen unzulässige UTF8-Zeichen
        if i in range(55296, 1 + 57343): continue
        
        ch = chr(i)
        index = nachsys(basis, i, ziffern)
        numBytesUTF8  = len(bytes(ch, 'utf8'))
        numBytesIndex = len(bytes(index, 'utf8'))
        cnt_UTF8[numBytesUTF8] += 1
        cnt_Index_Bytes[numBytesIndex] += 1
        cnt_Index_Ziffern[len(index)] += 1
        
        if zeigen:
            if numBytesIndex == 3:
                print("[%7d]  >%s<  >>%s<< " % (i, ch, index))
        
    # Listen-End-Elemente mit Wert 0 abschneiden, ausgenommen das letzte
    while cnt_Index_Bytes[-2] == 0:
        cnt_Index_Bytes = cnt_Index_Bytes[:-1]
    while cnt_Index_Ziffern[-2] == 0:
        cnt_Index_Ziffern = cnt_Index_Ziffern[:-1]
    
    # Summenberechnung für die Gesamtzahl der Bytes cnt_UTF8 und cnt_Index
    sum_BytesU = sum([ i*cnt_UTF8[i]  for i in range(len(cnt_UTF8)) ])
    sum_BytesI = sum([ i*cnt_Index_Bytes[i] for i in 
range(len(cnt_Index_Bytes)) ])
    diff = sum_BytesI - sum_BytesU
    quote = 100*sum_BytesI / sum_BytesU

    print("BytesUTF8     : %s"  % cnt_UTF8)
    print("BytesIndex    : %s"  % cnt_Index_Bytes)
    print("ZiffernIndex  : %s"  % cnt_Index_Ziffern)
    
    print("Σ Bytes UTF8  : %7d" % sum_BytesU)
    print("Σ Bytes Index : %7d" % sum_BytesI)
    
    print("Diff  (I - U) : %d" % diff)
    print("Quote (I : U) : %0.2f%%" % quote)
    print("Reduktion     : %0.2f%%" % (quote-100))
_______________________________________________
python-de Mailingliste -- python-de@python.org
Zur Abmeldung von dieser Mailingliste senden Sie eine Nachricht an 
python-de-le...@python.org
https://mail.python.org/mailman3/lists/python-de.python.org/
Mitgliedsadresse: arch...@mail-archive.com

Reply via email to