Macro ROUND_UP
dựa vào phân chia số nguyên để hoàn thành công việc. Nó sẽ chỉ hoạt động nếu cả hai tham số là số nguyên. Tôi giả định rằng N
là số cần làm tròn và S
là khoảng thời gian cần làm tròn. Tức là, ROUND_UP(12, 5)
phải trả lại 15, vì 15 là khoảng thời gian đầu tiên của 5 lớn hơn 12.
Hãy tưởng tượng chúng ta làm tròn thay vì lên. Trong trường hợp đó, macro sẽ chỉ đơn giản là:
#define ROUND_DOWN(N,S) ((N/S) * S)
ROUND_DOWN(12,5)
sẽ trở về 10, vì (12/5)
trong phân chia số nguyên là 2, và 2 * 5 là 10. Nhưng chúng tôi không làm ROUND_DOWN, chúng tôi đang làm ROUND_UP . Vì vậy, trước khi chúng tôi thực hiện phân chia số nguyên, chúng tôi muốn thêm nhiều nhất có thể mà không làm mất độ chính xác. Nếu chúng tôi thêm S
, nó sẽ hoạt động trong hầu hết mọi trường hợp; ROUND_UP(11,5)
sẽ trở thành ((((11 + 5)/5) * 5) và từ 16/5 trong phân số nguyên là 3, chúng tôi sẽ nhận được 15.
Sự cố xảy ra khi chúng tôi chuyển một số đã được làm tròn đến đa được chỉ định. ROUND_UP(10, 5)
sẽ trả về 15 và điều đó sai. Vì vậy, thay vì thêm S, chúng tôi thêm S-1. Điều này đảm bảo rằng chúng tôi sẽ không bao giờ đẩy thứ gì đó lên "xô" tiếp theo một cách không cần thiết.
Macro PAGE_
phải thực hiện với phép toán nhị phân. Chúng tôi sẽ giả vờ rằng chúng tôi đang xử lý các giá trị 8 bit vì mục đích đơn giản. Giả sử rằng PAGE_SIZE
là 0b00100000
. PAGE_SIZE-1
là như vậy 0b00011111
. ~(PAGE_SIZE-1)
sau đó là 0b11100000
.
Một số nhị phân &
sẽ xếp hai số nhị phân và để 1 ở bất kỳ đâu cả hai số đều có 1.Vì vậy, nếu x
là 0b01100111, các hoạt động sẽ đi như thế này:
0b01100111 (x)
& 0b11100000 (~(PAGE_SIZE-1))
------------
0b01100000
Bạn sẽ lưu ý rằng hoạt động thực sự chỉ zeroed-ra 5 bit cuối cùng. Đó là tất cả. Nhưng đó chính xác là hoạt động cần thiết để làm tròn xuống khoảng thời gian gần nhất là PAGE_SIZE
. Lưu ý rằng điều này chỉ làm việc vì PAGE_SIZE
chính xác là sức mạnh của 2. Nó giống như nói rằng đối với bất kỳ số thập phân tùy ý nào, bạn có thể làm tròn xuống 100 gần nhất đơn giản bằng cách zero-out hai chữ số cuối cùng. Nó hoạt động hoàn hảo, và thực sự dễ dàng để làm, nhưng sẽ không làm việc ở tất cả nếu bạn đang cố gắng làm tròn đến bội số gần nhất của 76.
PAGE_ROUND_UP
cũng làm như vậy, trang trước khi cắt nó đi. Đó là kinda như thế nào tôi có thể làm tròn lên bội số gần nhất của 100 bằng cách thêm 99 cho bất kỳ số nào và sau đó zeroing-out hai chữ số cuối cùng. (Chúng tôi thêm PAGE_SIZE-1
cho cùng một lý do chúng tôi đã thêm S-1
ở trên.)
Chúc bạn may mắn với bộ nhớ ảo!