Цілі особи
Як правило, ми не хочемо використовувати парні, тому що ми не хочемо використовувати операції з плаваючою точкою, помилки округлення тощо. Вони просто не потрібні.
Для цього непогано пам’ятати, як виконати поділ стелі: ceil(x / y)
в парних може бути записано як (x + y - 1) / y
(при цьому уникайте від’ємних цифр, але остерігайтеся переповнення).
Читабельна
Якщо ви хочете прочитати, ви, звичайно, також можете запрограмувати його так (наприклад, у Java, для C, звичайно, ви можете використовувати макроси):
public static int ceilDiv(int x, int y) {
return (x + y - 1) / y;
}
public static int paddedBase64(int n) {
int blocks = ceilDiv(n, 3);
return blocks * 4;
}
public static int unpaddedBase64(int n) {
int bits = 8 * n;
return ceilDiv(bits, 6);
}
// test only
public static void main(String[] args) {
for (int n = 0; n < 21; n++) {
System.out.println("Base 64 padded: " + paddedBase64(n));
System.out.println("Base 64 unpadded: " + unpaddedBase64(n));
}
}
Нарізний
Набивна
Ми знаємо, що нам потрібно 4 блоки символів на кожен 3 байти (або менше). Тоді формула стає (для x = n і y = 3):
blocks = (bytes + 3 - 1) / 3
chars = blocks * 4
або комбіновано:
chars = ((bytes + 3 - 1) / 3) * 4
ваш компілятор оптимізує 3 - 1
, тому просто залиште його так, щоб зберегти читабельність.
Незавантажений
Менш поширений варіант, що не розміщений, для цього ми пам’ятаємо, що кожному нам потрібен символ на кожні 6 біт, закруглені вгору:
bits = bytes * 8
chars = (bits + 6 - 1) / 6
або комбіновано:
chars = (bytes * 8 + 6 - 1) / 6
Однак ми все одно можемо розділити на два (якщо хочемо):
chars = (bytes * 4 + 3 - 1) / 3
Нечитабельна
Якщо ви не довіряєте своєму компілятору зробити остаточну оптимізацію для вас (або якщо ви хочете заплутати своїх колег):
Набивна
((n + 2) / 3) << 2
Незавантажений
((n << 2) | 2) / 3
Таким чином, ми маємо два логічні способи обчислення, і нам не потрібні гілки, розрядні або модульні операції - якщо тільки ми цього не хочемо.
Примітки:
- Очевидно, вам може знадобитися додати 1 до обчислень, щоб включити нульовий байт завершення.
- Для Mime вам може знадобитися подбати про можливі символи припинення рядків і подібні (шукайте інші відповіді на це).