Ganzzahlen
Im Allgemeinen möchten wir keine Doubles verwenden, da wir keine Gleitkommaoperationen, Rundungsfehler usw. verwenden möchten. Sie sind einfach nicht erforderlich.
Aus diesem Grund ist es eine gute Idee, sich daran zu erinnern, wie die Deckenteilung durchgeführt wird: ceil(x / y)
In Doppel kann geschrieben werden als (x + y - 1) / y
(unter Vermeidung negativer Zahlen, aber Vorsicht vor Überlauf).
Lesbar
Wenn Sie sich für die Lesbarkeit entscheiden, können Sie es natürlich auch so programmieren (Beispiel in Java, für C könnten Sie natürlich Makros verwenden):
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
Gepolstert
Wir wissen, dass wir jeweils 4 Zeichenblöcke für jeweils 3 Bytes (oder weniger) benötigen. Dann lautet die Formel (für x = n und y = 3):
blocks = (bytes + 3 - 1) / 3
chars = blocks * 4
oder kombiniert:
chars = ((bytes + 3 - 1) / 3) * 4
Ihr Compiler optimiert das 3 - 1
, lassen Sie es also einfach so, um die Lesbarkeit zu gewährleisten.
Ungepolstert
Weniger verbreitet ist die ungepolsterte Variante, dafür erinnern wir uns, dass wir jeweils ein Zeichen für jeweils 6 Bits benötigen, aufgerundet:
bits = bytes * 8
chars = (bits + 6 - 1) / 6
oder kombiniert:
chars = (bytes * 8 + 6 - 1) / 6
wir können jedoch immer noch durch zwei teilen (wenn wir wollen):
chars = (bytes * 4 + 3 - 1) / 3
Unlesbar
Falls Sie Ihrem Compiler nicht vertrauen, dass er die endgültigen Optimierungen für Sie vornimmt (oder wenn Sie Ihre Kollegen verwirren möchten):
Gepolstert
((n + 2) / 3) << 2
Ungepolstert
((n << 2) | 2) / 3
Es gibt also zwei logische Berechnungsmethoden, und wir brauchen keine Verzweigungen, Bit-Ops oder Modulo-Ops - es sei denn, wir wollen es wirklich.
Anmerkungen:
- Offensichtlich müssen Sie möglicherweise 1 zu den Berechnungen hinzufügen, um ein Nullterminierungsbyte einzuschließen.
- Für Mime müssen Sie sich möglicherweise um mögliche Zeilenabschlusszeichen und dergleichen kümmern (suchen Sie nach anderen Antworten dafür).