Возможно ли иметь кодировку в стиле UTF-8, ограниченную 3 байтами на символ? - PullRequest
2 голосов
/ 10 июня 2010

UTF-8 требует 4 байта для представления символов вне BMP. Это не плохо ; это не хуже, чем UTF-16 или UTF-32. Но это не оптимально (с точки зрения места для хранения).

Существует 13 байтов (C0-C1 и F5-FF), которые никогда не используются. И многобайтовые последовательности, которые не используются, например, те, которые соответствуют «слишком длинным» кодировкам. Если бы они были доступны для кодирования символов, то больше из них могли бы быть представлены 2-байтовыми или 3-байтовыми последовательностями (конечно, за счет усложнения реализации).

Можно ли представить все 1114 112 кодовых точек Unicode с помощью UTF-8-подобной кодировки с максимум 3 байтами на символ? Если нет, какое максимальное количество символов может представлять такая кодировка?

Под "UTF-8-like" я имею в виду, как минимум:

  • Байты 0x00-0x7F зарезервированы для символов ASCII.
  • Байт-ориентированные функции find / index работают правильно. Вы не можете найти ложное срабатывание, начав с середины символа, как в Shift-JIS.

Обновление - Моя первая попытка ответить на вопрос

Предположим, у вас есть классификация старших / конечных байтов в стиле UTF-8. Пусть:

  • A = количество однобайтовых символов
  • B = количество значений, используемых для начальных байтов 2-байтовых символов
  • C = количество значений, используемых для начальных байтов 3-байтовых символов
  • T = 256 - (A + B + C) = количество значений, используемых для конечных байтов

Тогда число символов, которое может поддерживаться, равно N = A + BT + CT².

Если A = 128, оптимум при B = 0 и C = 43. Это позволяет 310 803 символа, или около 28% пространства кода Unicode.

Есть ли другой подход, который может кодировать больше символов?

Ответы [ 3 ]

4 голосов
/ 10 июня 2010

Для записи всех кодовых точек Unicode потребуется чуть более 20 бит (при условии, что ваш номер правильный), оставляя более 3 бит из 24 для кодирования, какой байт какой. Этого должно быть достаточно.

Я не вижу, что вы получите от этого по сравнению с тем, что вы потеряете, если не будете придерживаться установленного стандарта.

Редактировать: Снова читая спецификацию, вы хотите, чтобы значения от 0x00 до 0x7f были зарезервированы для первых 128 кодовых точек. Это означает, что у вас есть только 21 бит в 3 байтах для кодирования оставшихся 1113984 кодовых точек. 21 бит - это едва ли достаточно, но на самом деле этого не достаточно, чтобы однозначно выполнить кодирование. Или, по крайней мере, я не нашел пути, поэтому я меняю свой ответ.

Что касается ваших мотиваций, то, конечно, нет ничего плохого в том, чтобы быть любопытным и участвовать в небольшом упражнении для мышления. Но смысл мысленного упражнения в том, чтобы сделать это самостоятельно , а не пытаться заставить весь интернет сделать это для вас! По крайней мере, будьте искренними, когда задаете свой вопрос.

2 голосов
/ 10 июня 2010

Я сделал математику, и это невозможно (если я хочу остаться строго "UTF-8-like").

Для начала, четырехбайтовый диапазон UTF-8 охватывает U+010000 to U+10FFFFЭто огромный кусок доступных персонажей.Это то, что мы пытаемся заменить, используя только 3 байта.

Благодаря специальному регистру каждого из 13 неиспользуемых байтов префикса, о которых вы упомянули, вы можете получить 65 536 символов каждый, что в итоге дает 13 * 0x10000 или 0xD0000.

Таким образом, общий диапазон 3-байтовых символов увеличится до U+010000 to U+0DFFFF, что почти все, но не вполне достаточно.

1 голос
/ 10 июня 2010

Конечно, это возможно. Доказательство:

2 24 = 16,777,216

Таким образом, достаточно места в битах для 1114,112 символов, но чем больше бит-пространства, тем больше битов используется на символ. Весь смысл UTF-8 состоит в том, что он предполагает, что нижние кодовые точки гораздо более вероятны в символьном потоке, поэтому все это будет весьма эффективно, даже если некоторые символы могут использовать 4 байта.

Предположим, что 0-127 остается одним байтом. Это оставляет 8.4M пробелов для 1.1M символов. Затем вы можете решить это уравнение. Выберите схему кодирования, где первый байт определяет, сколько байтов используется. Итак, есть 128 значений. Каждый из них будет представлять собой либо 256 символов (всего 2 байта), либо 65 536 символов (всего 3 байта). Итак:

256x + 65536 (128-x) = 1114112 - 128

Для решения этой проблемы вам необходимо 111 значений первого байта в виде 2-байтовых символов, а оставшихся 17 - 3-байтовых. Для проверки:

128 + 111 * 256 + 17 * 65536 = 1,114,256

Другими словами:

  • 128 кодовых точек требуют 1 байт;
  • 28 416 кодовых точек требуют 2 байта; и
  • 1114,112 кодовых точек требуют 3 байта.

Конечно, это не учитывает неизбежное расширение Unicode, как это делает UTF-8. Вы можете настроить это значение первого байта:

  • 0-127 (128) = 1 байт;
  • 128-191 (64) = 2 байта;
  • 192-255 (64) = 3 байта.

Это было бы лучше, потому что это простое побитовое И тестирует для определения длины и дает адресное пространство 4210816 кодовых точек.

...