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