关于round_up宏的问题 [英] Question about round_up macro

查看:167
本文介绍了关于round_up宏的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))

使用上面的宏,有人可以帮我理解(s)-1"部分吗,为什么?

With the above macro, could someone please help me on understanding the "(s)-1" part, why's that?

以及类似这样的宏:

#define PAGE_ROUND_DOWN(x) (((ULONG_PTR)(x)) & (~(PAGE_SIZE-1)))
#define PAGE_ROUND_UP(x) ( (((ULONG_PTR)(x)) + PAGE_SIZE-1)  & (~(PAGE_SIZE-1)) ) 

我知道(〜(PAGE_SIZE-1)))"部分会将最后五位清零,但除此之外,我一无所知,尤其是角色&"运算符播放.

I know the "(~(PAGE_SIZE-1)))" part will zero out the last five bits, but other than that I'm clueless, especially the role '&' operator plays.

谢谢

推荐答案

ROUND_UP宏依靠整数除法来完成工作.仅当两个参数均为整数时,它才有效.我假设N是要四舍五入的数字,而S是应该四舍五入的间隔.也就是说,ROUND_UP(12, 5)应该返回15,因为15是大于12的5的第一个间隔.

The ROUND_UP macro is relying on integer division to get the job done. It will only work if both parameters are integers. I'm assuming that N is the number to be rounded and S is the interval on which it should be rounded. That is, ROUND_UP(12, 5) should return 15, since 15 is the first interval of 5 larger than 12.

想象一下,我们是四舍五入而不是四舍五入.在这种情况下,宏将简单地是:

Imagine we were rounding down instead of up. In that case, the macro would simply be:

#define ROUND_DOWN(N,S) ((N / S) * S)

ROUND_DOWN(12,5)将返回10,因为整数除法中的(12/5)为2,而2 * 5为10.但是我们没有做ROUND_DOWN,而是做ROUND_UP.因此,在进行整数除法之前,我们希望在不损失精度的情况下尽可能多地添加.如果添加S,则几乎在所有情况下都可以使用; ROUND_UP(11,5)变为((((11 + 5)/5)* 5),由于整数除法中的16/5为3,我们得到15.

ROUND_DOWN(12,5) would return 10, because (12/5) in integer division is 2, and 2*5 is 10. But we're not doing ROUND_DOWN, we're doing ROUND_UP. So before we do the integer division, we want to add as much as we can without losing accuracy. If we added S, it would work in almost every case; ROUND_UP(11,5) would become (((11+5) / 5) * 5), and since 16/5 in integer division is 3, we'd get 15.

当我们传递一个已经舍入为指定倍数的数字时,就会出现问题. ROUND_UP(10, 5)将返回15,这是错误的.因此,我们添加S-1而不是添加S.这样可以确保我们永远不会不必要地将内容推入下一个存储桶".

The problem comes when we pass a number that's already rounded to the multiple specified. ROUND_UP(10, 5) would return 15, and that's wrong. So instead of adding S, we add S-1. This guarantees that we'll never push something up to the next "bucket" unnecessarily.

PAGE_宏与二进制数学有关.为了简单起见,我们假装正在处理8位值.假设PAGE_SIZE0b00100000.因此,PAGE_SIZE-10b00011111.那么~(PAGE_SIZE-1)0b11100000.

The PAGE_ macros have to do with binary math. We'll pretend we're dealing with 8-bit values for simplicity's sake. Let's assume that PAGE_SIZE is 0b00100000. PAGE_SIZE-1 is thus 0b00011111. ~(PAGE_SIZE-1) is then 0b11100000.

二进制&将排列两个二进制数字,并在两个数字都具有1的任何地方保留1.因此,如果x为0b01100111,则操作将如下所示:

A binary & will line up two binary numbers and leave a 1 anywhere that both numbers had a 1. Thus, if x was 0b01100111, the operation would go like this:

  0b01100111  (x)
& 0b11100000  (~(PAGE_SIZE-1))
------------
  0b01100000

您会注意到,该操作实际上仅将最后5位清零.就这样.但这恰恰是该操作需要四舍五入到最接近的PAGE_SIZE间隔.请注意,这仅是因为PAGE_SIZE的2的幂.这有点像说,对于任意十进制数字,只需将最后两位清零即可将其舍入到最接近的100.它运行完美,确实很容易,但是如果您想舍入到最接近的76的倍数,则根本无法工作.

You'll note that the operation really only zeroed-out the last 5 bits. That's all. But that was exactly that operation needed to round down to the nearest interval of PAGE_SIZE. Note that this only worked because PAGE_SIZE was exactly a power of 2. It's a bit like saying that for any arbitrary decimal number, you can round down to the nearest 100 simply by zeroing-out the last two digits. It works perfectly, and is really easy to do, but wouldn't work at all if you were trying to round to the nearest multiple of 76.

PAGE_ROUND_UP做同样的事情,但是在切断页面之前,它会尽可能多地添加到页面中.有点像是我可以通过将99加到任意数字并将 then 归零最后两位数字来四舍五入到最接近的100的倍数. (出于与上面添加S-1相同的原因,我们添加了PAGE_SIZE-1.)

PAGE_ROUND_UP does the same thing, but it adds as much as it can to the page before cutting it off. It's kinda like how I can round up to the nearest multiple of 100 by adding 99 to any number and then zeroing-out the last two digits. (We add PAGE_SIZE-1 for the same reason we added S-1 above.)

祝你虚拟内存好运!

这篇关于关于round_up宏的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆