После прочтения вики base64 ...
Я пытаюсь понять, как работает формула:
Учитывая строку с длиной n
, длина base64 будет
Который : 4*Math.Ceiling(((double)s.Length/3)))
Я уже знаю, что длина base64 должна %4==0
позволять декодеру знать, какова была исходная длина текста.
Максимальное количество отступов для последовательности может быть =
или ==
.
wiki: количество выходных байтов на входной байт составляет приблизительно 4/3 (33% накладных расходов)
Вопрос:
Как приведенная выше информация соответствует длине вывода ?
4 * n / 3
дает длину без подкладки.И округлить до ближайшего кратного 4 для заполнения, а поскольку 4 является степенью 2, можно использовать побитовые логические операции.
источник
$(( ((4 * n / 3) + 3) & ~3 ))
4 * n / 3
уже завершается с ошибкойn = 1
, один байт кодируется с использованием двух символов, и в результате ясно, что один символ.Для справки формула длины кодера Base64 выглядит следующим образом:
Как вы сказали, кодер Base64 с данными в
n
байтах данных создаст строку4n/3
символов Base64. Другими словами, каждые 3 байта данных приведут к 4 символам Base64. РЕДАКТИРОВАТЬ : комментарий правильно указывает, что мой предыдущий рисунок не учитывал отступы; правильная формулаCeiling(4n/3)
.В статье Википедии показано, как именно строка ASCII,
Man
закодированная в строку Base64,TWFu
в своем примере. Входная строка имеет размер 3 байта или 24 бита, поэтому формула правильно предсказывает, что вывод будет иметь длину 4 байта (или 32 бита):TWFu
. Процесс кодирует каждые 6 бит данных в один из 64 символов Base64, поэтому 24-битный ввод, разделенный на 6, дает 4 символа Base64.Вы спрашиваете в комментарии, каков будет размер кодировки
123456
. Учитывая, что каждый символ этой строки имеет размер 1 байт или 8 бит (при условии кодирования ASCII / UTF8), мы кодируем 6 байтов или 48 бит данных. Согласно уравнению, мы ожидаем, что выходная длина будет(6 bytes / 3 bytes) * 4 characters = 8 characters
.Помещение
123456
в кодировщик Base64 создаетMTIzNDU2
, длина которого составляет 8 символов, как мы и ожидали.источник
floor((3 * (length - padding)) / 4)
. Проверьте следующую суть .Целые
Обычно мы не хотим использовать удвоения, потому что мы не хотим использовать операции с плавающей запятой, ошибки округления и т. Д. Они просто не нужны.
Для этого полезно вспомнить, как выполнить деление потолка:
ceil(x / y)
в парном разряде можно записать как(x + y - 1) / y
числах (избегая отрицательных чисел, но остерегаясь переполнения).Удобочитаемый
Если вы стремитесь к читабельности, вы, конечно, можете также запрограммировать это так (например, на Java, для C вы, конечно, можете использовать макросы):
встраиваемый
подбитый
Мы знаем, что нам нужно 4 блока символов одновременно на каждые 3 байта (или меньше). Итак, формула становится (для x = n и y = 3):
или в сочетании:
Ваш компилятор оптимизирует
3 - 1
, так что просто оставьте его таким, чтобы сохранить читабельность.без ведущего
Менее распространенным является вариант без дополнения, для этого мы помним, что для каждого нам нужен символ для каждых 6 битов, округленный в большую сторону:
или в сочетании:
однако мы можем все еще разделить на два (если мы хотим):
нечитаемый
Если вы не доверяете вашему компилятору окончательную оптимизацию (или если вы хотите запутать своих коллег):
подбитый
без ведущего
Итак, у нас есть два логических способа вычисления, и нам не нужны никакие ветки, битовые операции или операции по модулю - если мы действительно этого не хотим.
Ноты:
источник
Я думаю, что данные ответы не соответствуют сути исходного вопроса, который заключается в том, сколько места нужно выделить для соответствия кодировке base64 для данной двоичной строки длиной n байтов.
Ответ
(floor(n / 3) + 1) * 4 + 1
Это включает отступы и завершающий нулевой символ. Вам, возможно, не понадобится слово в пол, если вы делаете целочисленную арифметику.
Включая заполнение, для строки base64 требуется четыре байта на каждый трехбайтовый фрагмент исходной строки, включая любые частичные фрагменты. Один или два байта в конце строки будут преобразованы в четыре байта в строке base64 при добавлении заполнения. Если у вас нет особого использования, лучше всего добавить заполнение, обычно это знак равенства. Я добавил дополнительный байт для нулевого символа в C, потому что строки ASCII без этого немного опасны, и вам нужно было бы переносить длину строки отдельно.
источник
Вот функция для вычисления исходного размера закодированного файла Base 64 как строки в килобайтах:
источник
В то время как все остальные обсуждают алгебраические формулы, я бы предпочел просто использовать сам BASE64, чтобы сказать мне:
525
710
Таким образом, кажется, что формула из 3 байтов, представленных 4 символами base64, кажется правильной.
источник
(В попытке дать краткое, но полное деривация.)
Каждый входной байт имеет 8 битов, поэтому для n входных байтов мы получаем:
Каждые 6 битов являются выходными байтами, поэтому:
Это без дополнения.
С отступом мы округляем это до нескольких из четырех выходных байтов:
См. Вложенные подразделения (Wikipedia) для первой эквивалентности.
Использование целочисленной арифметики, CEIL ( п / м ) может быть рассчитано как ( п + т - 1) Div м , следовательно , мы получаем:
Для иллюстрации:
Наконец, в случае кодирования MIME Base64 необходимы два дополнительных байта (CR LF) на каждые 76 выходных байтов, округленных в большую или меньшую сторону в зависимости от того, требуется ли завершающий символ новой строки.
источник
Сдается мне, что правильная формула должна быть:
источник
Я считаю, что это точный ответ, если n% 3 не ноль, нет?
Версия Mathematica:
Радоваться, веселиться
солдат
источник
Простая реализация в JavaScript
источник
Для всех людей, которые говорят на C, взгляните на эти два макроса:
Взято отсюда .
источник
Я не вижу упрощенной формулы в других ответах. Логика покрыта, но я хотел основную форму для моего встроенного использования:
ПРИМЕЧАНИЕ. При подсчете количества незаполненных полей мы округляем целочисленное деление, т.е. добавляем делитель-1, который в данном случае равен +2.
источник
В Windows - я хотел оценить размер буфера размером mime64, но все точные формулы расчета не работали для меня - в конце концов я получил приблизительную формулу, подобную этой:
Размер выделения строки в Mine64 (приблизительный) = (((4 * ((размер двоичного буфера) + 1)) / 3) + 1)
Таким образом, последний +1 - он используется для ascii-zero - последний символ должен быть выделен для хранения нулевого окончания - но почему «двоичный размер буфера» равен + 1 - я подозреваю, что есть какой-то символ завершения mime64? Или, может быть, это какая-то проблема выравнивания.
источник
Если кто-то заинтересован в достижении решения @Pedro Silva в JS, я просто перенес это решение:
источник