فرانكلين بيزوتي دير

الرئيسية     مدونات     السيرة الذاتية     اتصل بي     الناس     RSS

Ein Shitpost über die Hochzahlen in Unicode

Ich setzte mich daran, ein Bisschen Code in C++ zu schreiben, um mit Polynomen zu rechnen. Zu meinem eigenen Nutzen wollte ich eine Funktion schreiben, die die als Koeffizientvektoren kodierte Polynomen in eineme Terminal schön abbilden könne. Natürlich hatte ich die Absicht, die speziale Unicode-Zeichen ⁰¹²³⁴⁵⁶⁷⁸⁹ dazu zu benützen, weil x⁵ sehr schöner als x^5 aussieht. Anfänglich entwickelte ich eine Funktion, die jede Ziffer von 0 bis 9 in sein hochgestelltes Gegenstück von Unicode beziehungsweise übersetzen könnte.

char digit_superscript(int d) {
   // some stuff here...
}

Aber das klappt nicht. Jedes mit UTF8 codierte Unicode-Zeichen kann aus bis vier Bytes bestehen. Ein char kann nur ein einziges Byte enthalten und deshalb musste ich stattdessen ein string zurückgeben.

string digit_superscript(int d) {
   // some stuff here...
}

Am einfachsten (und wahrscheinlich am schnellsten) könnte man zehn hartkodierte Fälle auflisten und das angemessene Unicode-Zeichen in jedem Fall zurückgeben. Solcher Code wäre doch sehr unangenehm und repetitiv und es ist mir egal, wie schell meine Polynomen gedruckt werden. Mir fiel eine alte Methode ein, die mir gute Dienste bei der Bearbeitung von ASCII-Zeichen geleistet hat: um den n-te Buchstabe vom Alphabet zu holen, kann man einfach $n$ mit dem Zeichen 'a' versetzen, weil die Buchstaben a..z konsekutiv sind. Vielleicht könnte man die Hochzahl $d$ von einem mit $d$ versetzten Zeichen erreichen.

Dem Unicode-Zeichen entspricht das Codepoint U+2070, das in UTF8 mit den Bytes e2 81 b0 kodiert wird. Ich probierte es aus:

string digit_superscript(int d) {
   string num = "\xe2\x81\xb0";
   num.at(2) += d;
   return num;
}

Dann versuchte ich, die Ziffer ab null bis neun abzubilden, um diese Funktion zu prüfen:

int main() {
   for (int i = 0; i < 10; i++)
      cout << digit_superscript(i);
   cout << "\n";
}

Die Ausgabe: ⁰ⁱ⁲⁳⁴⁵⁶⁷⁸⁹. Verdammt nochmal!

So ist es: die Unicode-Hochzahlen sind gar nicht konsekutiv. Das hochgestellte Nullzeichen hat das Codepoint U+2070 aber dem Codepoint U+2071 entspricht das hochstellte "i"-Zeichen . Damit nicht genug, die Codepoints U+2072 und U+2073 entsprechen gar keinen Zeichen und sie sind "für spätere Nutzung reserviert". Glücklicherweise bewohnen die Hochzahlen ⁴⁵⁶⁷⁸⁹ die konsekutive Codepoints von U+2074 bis U+2079.

Was ist denn mit ¹²³ los? Laut Wikipedia sind sie von der Codierung ISO-8859-1, die eine einbytige ASCII erweiternde Codierung mit nur diesen drei Hochzahlen und keinen von den anderen ist, übergenommen. Um diese Kodierung zu beachten hat Unicode die ISO-8859-1-Zeichen ihre beziehungsweise Codepoints in seinem Block Latin-1 behalten gelassen, aber diese Entscheidung hat eine peinliche Folge: die Hochzahlen ¹²³ sind ungefähr 8000 Codepoints von ihren Geschwistern getrennt. Mindestens hat den Sonderling als Gesellschaft. Sie sind irgendwie verwandt, nicht wahr? Weil sie beide so hochgeschriebene... Dinge sind?

Es kommt noch dicker: innerhalb ISO-8859-1 sind ¹²³ auch nicht konsekutiv. Die Zeichen ²³ sind U+00B2 und U+00B3 aber ¹ ist U+00B9. Na, ausgezeichnet.

Fig1

Zurück zum Programmieren: Für die Ziffern ⁰⁴⁵⁶⁷⁸⁹ benutzte ich die Versetzens-Technik aber für die Ziffern ¹²³ waren abgesonderte Spezialfälle nötig.

string digit_superscript(int d) {
   switch (d) {
      case 1:
         return "\u00b9";
      case 2:
         return "\u00b2";
      case 3:
         return "\u00b3";
      default:
         string num = "\xe2\x81\xb0";
         num.at(2) += d;
         return num;
   }
}

Wie schrecklich...


قفز الى الرئيسية
The posts on this website are licensed under CC-by-NC 4.0.