Entiers
En général, nous ne voulons pas utiliser de doubles parce que nous ne voulons pas utiliser les opérations en virgule flottante, les erreurs d'arrondi, etc. Elles ne sont tout simplement pas nécessaires.
Pour cela, il est bon de se rappeler comment effectuer la division du plafond: ceil(x / y)
en double peut être écrit comme(x + y - 1) / y
(en évitant les nombres négatifs, mais attention aux débordements).
Lisible
Si vous optez pour la lisibilité, vous pouvez bien sûr également le programmer comme ceci (exemple en Java, pour C, vous pouvez utiliser des macros, bien sûr):
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));
}
}
Inline
Rembourré
Nous savons que nous avons besoin de 4 blocs de caractères à la fois pour chaque 3 octets (ou moins). Alors la formule devient (pour x = n et y = 3):
blocks = (bytes + 3 - 1) / 3
chars = blocks * 4
ou combiné:
chars = ((bytes + 3 - 1) / 3) * 4
votre compilateur optimisera le 3 - 1
, alors laissez-le comme ceci pour maintenir la lisibilité.
Non rembourré
Moins commune est la variante non rembourrée, pour cela, nous nous souvenons que chacun nous avons besoin d'un caractère pour chaque 6 bits, arrondi:
bits = bytes * 8
chars = (bits + 6 - 1) / 6
ou combiné:
chars = (bytes * 8 + 6 - 1) / 6
on peut cependant encore diviser par deux (si on veut):
chars = (bytes * 4 + 3 - 1) / 3
Illisible
Si vous ne faites pas confiance à votre compilateur pour faire les optimisations finales à votre place (ou si vous voulez confondre vos collègues):
Rembourré
((n + 2) / 3) << 2
Non rembourré
((n << 2) | 2) / 3
Nous sommes donc là, deux méthodes logiques de calcul, et nous n'avons pas besoin de branches, d'opérations de bits ou d'opérations modulo - à moins que nous ne le voulions vraiment.
Remarques:
- De toute évidence, vous devrez peut-être ajouter 1 aux calculs pour inclure un octet de terminaison nul.
- Pour Mime, vous devrez peut-être faire attention aux éventuels caractères de terminaison de ligne et autres (cherchez d'autres réponses pour cela).