C / C ++整数运算

时间:2009-11-11 04:57:35

标签: c math

我偶然发现了

int a = (h/2)*w+ (  (h+1)/2-h/2   )  *  (w+1)/2 ;

等于

int b = (w * h + 1) / 2 ;

当w和h是正整数时(假设没有溢出)。

你能告诉我为什么这两个是一样的吗?

编辑:整数 - >正整数。

4 个答案:

答案 0 :(得分:8)

为了简化表达,您必须考虑四种情况:

  • h even and w even
  • h even and w odd
  • h odd and w even
  • h odd and w odd

从那里开始,并应用适当的整数截断规则,您应该能够简化为第二个表达式。

答案 1 :(得分:7)

实际上这是一个数学问题:(整数)/ 2应该被解释为floor。所以,问题是:

  

显示floor(h/2)*w + ( floor((h+1)/2) - floor(h/2) ) * floor((w+1)/2)等同于floor((w*h+1)/2)

证明:

  1. h = 2k,w = 2l :(两个数字都是偶数)......
  2. h = 2k + 1,w = 2l:...
  3. h = 2k,w = 2l + 1:......
  4. h = 2k + 1,w = 2k + 1:......
  5. 提示:floor((2k+1)/2) == k。您可以轻松显示等效性。

    例如,案例4:

    a)floor(2k+1/2)*(2l+1) + ( floor((2k+2)/2) - floor((2k+1)/2) ) * floor((2l+2)/2) = 2kl+k + (k+1 - k)*(l+1) = 2kl + k + l + 1

    b)floor(((2k+1)*(2l+1)+1)/2) = floor((4kl+2k+2l+2)/2) = 2kl + k + l + 1

    因此,这两个方程是等价的。

答案 2 :(得分:1)

有趣的是,这个问题说它是平等的,当你测试几个偶数和奇数值时它似乎就是这样。但这很容易枯燥的数学,所以没有人检查所有的情况。我也很懒,而且,即使我更像一个数学家,我还是使用一些复制粘贴进行了快速计算机检查:

bool diff = false;
int n = 100;
for(int w = -n; w<n; ++w){
    for(int h = -n; h<n; ++h){
        int a = (h/2)*w+ (  (h+1)/2-h/2   )  *  (w+1)/2 ;
        int b = (w * h + 1) / 2;
        if (a!=b) diff = true;
    }
}
cout << (diff ? "a != b" : "a == b") << endl;

我发现它不等于w = -1和h = -1,很容易检查a = 0和b = 1.这就是“简单的简化”经常引入新的bug。

PS:公平地说,我猜w和h是宽度和高度,所以它们可能总是正面的。但是没有指定(并且根据经验,其他一些代码可能会返回负宽度)

答案 3 :(得分:0)

这是一个直接的数学问题。只需证明以下内容:

(h / 2)* w +((h + 1)/ 2-h / 2)*(w + 1)/ 2 =(w * h + 1)/ 2