จำนวนเต็ม
โดยทั่วไปเราไม่ต้องการใช้คู่ผสมเพราะเราไม่ต้องการใช้จุดลอยตัวข้อผิดพลาดในการปัดเศษเป็นต้นพวกมันไม่จำเป็น
สำหรับเรื่องนี้เป็นความคิดที่ดีที่จะจำวิธีการแบ่งเพดาน: 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));
}
}
inlined
มีเบาะ
เรารู้ว่าเราต้องการบล็อก 4 ตัวอักษรในแต่ละครั้งสำหรับ 3 ไบต์ (หรือน้อยกว่า) ดังนั้นสูตรจะกลายเป็น (สำหรับ x = n และ y = 3):
blocks = (bytes + 3 - 1) / 3
chars = blocks * 4
หรือรวม:
chars = ((bytes + 3 - 1) / 3) * 4
คอมไพเลอร์ของคุณจะปรับให้เหมาะสม3 - 1
ดังนั้นเพียงปล่อยไว้เช่นนี้เพื่อรักษาความสามารถในการอ่าน
unpadded
ที่พบได้น้อยกว่าคือตัวแปรที่ไม่เพิ่มจำนวนสำหรับเรื่องนี้เราจำได้ว่าเราแต่ละคนต้องการอักขระสำหรับแต่ละ 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
unpadded
((n << 2) | 2) / 3
ดังนั้นเราจึงมีสองวิธีในการคำนวณแบบตรรกะและเราไม่ต้องการสาขาใด ๆ บิต -ops หรือ modulo ops - เว้นแต่ว่าเราต้องการ
หมายเหตุ:
- เห็นได้ชัดว่าคุณอาจต้องเพิ่ม 1 ในการคำนวณเพื่อรวมไบต์การเลิกจ้างที่เป็นโมฆะ
- สำหรับ Mime คุณอาจต้องดูแลตัวอักขระการสิ้นสุดบรรทัดที่เป็นไปได้และเช่นนั้น (มองหาคำตอบอื่นสำหรับสิ่งนั้น)