Enteros
Generalmente no queremos usar dobles porque no queremos usar operaciones de coma flotante, errores de redondeo, etc. Simplemente no son necesarios.
Para esto, es una buena idea recordar cómo realizar la división del techo: ceil(x / y)
en dobles se puede escribir como (x + y - 1) / y
(evitando números negativos, pero tenga cuidado con el desbordamiento).
Legible
Si opta por la legibilidad, por supuesto, también puede programarlo de esta manera (por ejemplo, en Java, para C podría usar macros, por supuesto):
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));
}
}
En línea
Acolchado
Sabemos que necesitamos bloques de 4 caracteres a la vez por cada 3 bytes (o menos). Entonces la fórmula se convierte (para x = ny e = 3):
blocks = (bytes + 3 - 1) / 3
chars = blocks * 4
o combinado:
chars = ((bytes + 3 - 1) / 3) * 4
su compilador optimizará el 3 - 1
, así que déjelo así para mantener la legibilidad.
Sin relleno
Menos común es la variante sin relleno, para esto recordamos que cada uno necesitamos un carácter para cada 6 bits, redondeado:
bits = bytes * 8
chars = (bits + 6 - 1) / 6
o combinado:
chars = (bytes * 8 + 6 - 1) / 6
sin embargo, aún podemos dividir por dos (si queremos):
chars = (bytes * 4 + 3 - 1) / 3
Ilegible
En caso de que no confíe en su compilador para hacer las optimizaciones finales por usted (o si quiere confundir a sus colegas):
Acolchado
((n + 2) / 3) << 2
Sin relleno
((n << 2) | 2) / 3
Así que ahí estamos, dos formas lógicas de cálculo, y no necesitamos ninguna rama, bit-ops u modulo ops, a menos que realmente lo queramos.
Notas:
- Obviamente, es posible que deba agregar 1 a los cálculos para incluir un byte de terminación nulo.
- Para Mime, es posible que deba ocuparse de los posibles caracteres de terminación de línea y demás (busque otras respuestas para eso).