整数
浮動小数点演算、丸め誤差などを使用したくないため、通常、doubleは使用しません。これらは必要ありません。
このため、天井の除算を実行する方法を覚えておくことをお勧めします。doubleでは、次の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));
}
}
インライン化
パッド入り
3バイト(またはそれ以下)ごとに一度に4文字のブロックが必要であることがわかっています。したがって、式は次のようになります(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
ただし、(必要に応じて)2で割ることはできます。
chars = (bytes * 4 + 3 - 1) / 3
読めない
コンパイラが最終的な最適化を行うことを信頼していない場合(または同僚を混乱させたい場合):
パッド入り
((n + 2) / 3) << 2
パッドなし
((n << 2) | 2) / 3
つまり、2つの論理的な計算方法があり、本当に必要な場合を除いて、分岐、ビット演算、モジュロ演算は必要ありません。
ノート:
- 明らかに、ヌル終了バイトを含めるには、計算に1を追加する必要がある場合があります。
- Mimeの場合、行末文字などの可能性に注意する必要がある場合があります(他の回答を探してください)。