了解CEILING宏用例

2jcobegt  于 2023-06-05  发布在  其他
关注(0)|答案(6)|浏览(107)

我在代码库的一个实用程序头中发现了以下宏:

#define CEILING(x,y) (((x) + (y) - 1) / (y))

this answer的帮助下,我将其解析为:

// Return the smallest multiple N of y such that:
//   x <= y * N

但是,无论我如何盯着这个宏在我们的代码库中是如何使用的,我都无法理解这样一个操作的价值。没有任何用法被注解,这似乎表明它是显而易见的。
谁能用英语解释一下这个宏的用例?很明显,我就是看不出来...

hof1towb

hof1towb1#

假设你想分块分配内存(想想:高速缓存行、磁盘扇区);需要多少内存才能容纳整数个包含X字节的块?如果卡盘尺寸为Y,则答案为:CEILING(X,Y)

ukxgm1gy

ukxgm1gy2#

当你像这样在C中使用整数除法时

y = a / b

你会得到一个四舍五入的除法结果,即5 / 2 == 2-5 / 2 == -2。有时候需要用另一种方式舍入它,例如,如果你想用最小的整数数组大小来容纳n字节,你会希望n / sizeof(int)向上舍入,因为你想用空间来容纳额外的字节。
这个宏就是这样做的:CEILING(5,2) == 3,但请注意,它只适用于正y,所以要小心。

mcvgt66p

mcvgt66p3#

嗯……英语例子……你只能买五根一捆的香蕉。有47个人想要香蕉。你需要多少束?答案= CEILING(47,5)=((47 + 5)- 1)/ 5 = 51 / 5 = 10(去掉余数-整数除法)。

lymnna71

lymnna714#

让我们尝试一些测试值

CEILING(6, 3) = (6 + 3 -1) / 3 = 8 / 3 = 2 // integer division
CEILING(7, 3) = (7 + 3 -1) / 3 = 9 / 3 = 3
CEILING(8, 3) = (8 + 3 -1) / 3 = 10 / 3 = 3
CEILING(9, 3) = (9 + 3 -1) / 3 = 11 / 3 = 3
CEILING(10, 3) = (9 + 3 -1) / 3 = 12 / 3 = 4

正如你所看到的,宏的结果是一个整数,最小的可能z满足:z * y >= x
我们也可以尝试使用符号:

CEILING(k*y, y) = (k*y + y -1) / y = ((k+1)*y - 1) / y = k
CEILING(k*y + 1, y) = ((k*y + 1) + y -1) / y = ((k+1)*y) / y = k + 1
CEILING(k*y + 2, y) = ((k*y + 2) + y -1) / y = ((k+1)*y + 1) / y = k + 1
....
CEILING(k*y + y - 1, y) = ((k*y + y - 1) + y -1) / y = ((k+1)*y + y - 2) / y = k + 1
CEILING(k*y + y, y) = ((k*y + y) + y -1) / y = ((k+1)*y + y - 1) / y = k + 1
CEILING(k*y + y + 1, y) = ((k*y + y + 1) + y -1) / y = ((k+2)*y) / y = k + 2

你可以用它来分配一个常数倍数大小的内存,来决定需要多少块来填满一个屏幕,等等。
不过要小心这只适用于正的y
希望能帮上忙。

vfhzx4xs

vfhzx4xs5#

假设y > 0CEILING(x,y)给出了x/y的上限(数学除法)。其中一个用例是从偏移量x开始的素数筛,您可以将筛范围中素数y的所有倍数标记为复合。

guicsvcw

guicsvcw6#

我知道这个问题很久以前了,但我找到了为什么你会使用这样的宏的原因,在C++中你有定义ceil(double x)的std,但它实际上有一个缺陷:当你试图在里面执行除法时,你会得到一个四舍五入的参数。考虑一下这个codeforces问题:B. Long Legs。它是使用以下公式的蛮力求解的:

现在如果你使用stdceil,你会得到完全错误的值,因为参数中的类型转换;

main(){
    ll t;
    cin >> t;
    while(t--){
      ll a , b;
      cin >> a >> b;
      ll k = a+b;
      for(ll i = 2; i <= 10e5;i++){
        ll val = std::ceil(a/i) + std::ceil(b/i) + i-1;
        k = min(k , val);
      }
      cout << k << "\n";

    }
    return 0;
}

输出(错误)

1
4
5

现在使用正确的宏

#define ceil(x,y) (((x) + (y) - 1) / (y))

main(){
    ll t;
    cin >> t;
    while(t--){
      ll a , b;
      cin >> a >> b;
      ll k = a+b;
      for(ll i = 2; i <= 10e5;i++){
        ll val = ceil(a,i) + ceil(b,i) + i-1;
        k = min(k , val);
      }
      cout << k << "\n";

    }
    return 0;
}

输出(正确)

2
5
6

如果你仍然想使用std::ceil,你可以这样做:
std::ceil((double)a/i) + std::ceil((double)b/i) + i-1;

相关问题