计算给定范围内偶数的最简单方法

时间:2010-04-21 11:29:16

标签: c math

计算无符号整数范围内偶数的最简单方法是什么?

一个例子:如果范围是[0 ... 4]则答案是3(0,2,4)

我很难想出任何简单的方法。我提出的唯一解决方案涉及几个if语句。是否有一行简单的代码可以在没有if语句或三元运算符的情况下执行此操作?

16 个答案:

答案 0 :(得分:14)

int even = (0 == begin % 2) ? (end - begin) / 2 + 1 : (end - begin + 1) / 2;

哪些可以转换为:

int even = (end - begin + (begin % 2)) / 2 + (1 - (begin % 2));

编辑:这可以进一步简化为:

int even = (end - begin + 2 - (begin % 2)) / 2;

EDIT2:由于我认为C中的整数除法有些不正确的定义(整数除法向下截断正数而向上截断为负数)此公式在begin为a时不起作用负奇数。

EDIT3:用户“iPhone初学者”正确观察到,如果begin % 2替换为begin & 1,则此功能将适用于所有范围。

答案 1 :(得分:7)

提示1:模运算符将返回当前数字的剩余部分
提示2:您不需要for循环
提示3:范围是连续的 提示4:连续范围内偶数的数量是偶数的一半(有时是半+ 1,有时是半 - 1) 提示5:建立在提示1上:还要考虑(+结束+ 1)%2给出的内容 提示6:此主题中的大部分或全部答案都是错误的 提示7:确保您尝试使用负数范围的解决方案 提示8:确保您尝试的解决方案的范围涵盖负数和正数

答案 2 :(得分:2)

int start, stop;
start = 0;
stop = 9;
printf("%d",(stop-start)/2+((!(start%2) || !(stop%2)) ? 1 : 0));

开始停止可以保留任何值。 无需迭代来确定此数字。

答案 3 :(得分:2)

0到 n 之间的偶数计数是[ n / 2] + 1.因此,( n + 1)和 m 是([ m / 2] + 1) - ([ n / 2] + 1)= [< em> m / 2] - [ n / 2]。

对于 m n 之间的偶数计数,因此答案为[ m / 2] - [( n - 1)/ 2]。

[x]指向 - \ infty的方向。请注意,在我们的情况下,通常的C整数除法不正确:a/2向零舍入,而不是 - \ infty,因此结果将不是[ a / 2]对于teh负面情况 a

这应该是最简单的计算;也适用于负数。 (但需要 m &gt; = n 。)不包含if?: s。

如果您不考虑负数,则可以只使用m/2 - (n+1)/2 + 1,否则floor(m/2.0) - floor((n-1)/2.0)

答案 4 :(得分:2)

即使对于负数范围也是如此。

int even = (last - first + 2 - Math.abs(first % 2) - Math.abs(last % 2)) / 2;

使用以下代码进行测试:

public static void main(String[] args) {
    int[][] numbers = {{0, 4}, {0, 5}, {1, 4}, {1, 5}, {4, 4}, {5, 5},
                       {-1, 0}, {-5, 0}, {-4, 5}, {-5, 5}, {-4, -4}, {-5, -5}};

    for (int[] pair : numbers) {
        int first = pair[0];
        int last = pair[1];
        int even = (last - first + 2 - Math.abs(first % 2) - Math.abs(last % 2)) / 2;
        System.out.println("[" + first + ", " + last + "] -> " + even);
    }
}

输出:

[0, 4] -> 3
[0, 5] -> 3
[1, 4] -> 2
[1, 5] -> 2
[4, 4] -> 1
[5, 5] -> 0
[-1, 0] -> 1
[-5, 0] -> 3
[-4, 5] -> 5
[-5, 5] -> 5
[-4, -4] -> 1
[-5, -5] -> 0

答案 5 :(得分:2)

答案是使用二进制AND。

因此,数字以0和1表示在内存中。 让我们说4和5。

4 = 0000 0100

5 = 0000 0101

每个偶数结尾都为零,每个奇数结尾都为1;

在c中,“ 1”表示正确,而“ 0”表示错误。

所以:让代码;

function isEven(int num){
     return ((num & 0x01) == 0) ? 1 : 0;
}

此处0x01表示0000 0001。 所以我们将0x01与给定的数字相加。

想象不为5

5    |0000 0101 

0x01 |0000 0001

---------------

      0000 0001

因此答案将为“ 1”。

想象不为4

4    |0000 0100 

0x01 |0000 0001

---------------

      0000 0000

因此答案将为“ 0”。

现在

return ((num & 0x01) == 0) ? 1 : 0;

它在中展开:

if((num & 0x01) == 0){// means  the number is even
      return 1;
}else{//means no is odd
      return 0;
}

这就是全部。

结尾是二进制运算符,在竞争性编程世界中非常重要。

快乐的编码。

第一个答案。

编辑1:

偶数总数

totalEvens = ((end - start) / 2 + ((((end - start) & 0x01 ) == 0) ? 0 : 1 ));

在这里 (end - start)/2给出总数的一半。

如果一个是偶数而一个是奇数,这将起作用。

但是

((((end - start) & 0x01 ) == 0) ? 0 : 1 )

可以用(!isEven(end-start))

代替

因此,如果总数为偶数,则不要加1,否则加1。

这完全有效。

答案 6 :(得分:1)

范围始终是[2a + b,2c + d],b,d = {0,1}。制作一张桌子:

b d | #even
0 0 | c-a+1
0 1 | c-a+1
1 0 | c-a
1 1 | c-a+1

现在a = min / 2,b = min%2,c = max / 2和d = max%2。

所以int nEven = max/2 - min/2 + 1 - (min%2)

答案 7 :(得分:1)

我有点惊讶迭代试图解决这个问题。 一个范围内可能的偶数最小数量等于数字数组长度的一半,或者rangeEnd - rangeStart。 如果第一个或最后一个数字是偶数,则加1。

所以方法是:(使用javascript)

function evenInRange(rangeStart, rangeEnd)
{
  return
    Math.floor(rangeEnd - rangeStart) + 
    ((rangeStart % 2 == 0) || (rangeEnd % 2 == 0) ? 1 : 0)
}


Tests:
0 1 2 3 4 5 6 7 8
8 - 0 = 8
8 / 2 = 4
4 + 1 = 5
Even numbers in range:
0 2 4 6 8

11 12 13 14 15 16 17 18 19 20
20 - 11 = 9
9 / 2 = 4
4 + 1 = 5
Even numbers in range
12 14 16 18 20

1 2 3
3 - 1 = 2
2 / 2 = 1
1 + 0 = 1
Even numbers in range
2

2 3 4 5
5 - 2 = 3
3 / 2 = 1
1 + 1 = 2
Even numbers in range
2 4

2 3 4 5 6
6 - 2 = 4
4 / 2 = 2
2 + 1 = 3
Even numbers in range
2 4 6

答案 8 :(得分:0)

我会说

(max - min + 1 + (min % 2)) / 2

编辑:呃好吧因为某种原因我认为(min%2)为偶数数字返回1 .... :)。正确的版本是

(max - min + 1 + 1 - (min % 2)) / 2

或者更确切地说

(max - min + 2 - (min % 2)) / 2

答案 9 :(得分:0)

范围中的第一个偶数是:(begin + 1) & ~1(圆begin到偶数)。

范围内的最后一个偶数是:end & ~1(将end舍入为偶数)。

因此,范围内的偶数总数为:(end & ~1) - ((begin + 1) & ~1) + 1

int num_evens = (end & ~1) - ((begin + 1) & ~1) + 1;

答案 10 :(得分:0)

让我们从逻辑上看这个......

我们有四个案例......

odd -> odd     eg.  1 -> 3  answer: 1
odd -> even    eg.  1 -> 4  answer: 2
even -> odd    eg.  0 -> 3  answer: 2
even -> even   eg.  0 -> 4  answer: 3

前三种情况可以简单地处理为......

(1 + last - first) / 2

第四种情况并没有很好地融入其中,但我们可以很容易地对它进行一点点捏造......

answer = (1 + last - first) / 2;
if (both first and last are even)
    answer++;

希望这有帮助。

答案 11 :(得分:0)

哦,好吧,为什么不呢:

#include <cassert>

int ecount( int begin, int end ) {
    assert( begin <= end );
    int size = (end - begin) + 1;
    if ( size % 2 == 0  || begin % 2 == 1 ) {
        return size / 2;
    }
    else {
        return size / 2 + 1;
    }
}

int main() {
    assert( ecount( 1, 5 ) == 2 );
    assert( ecount( 1, 6 ) == 3 );
    assert( ecount( 2, 6 ) == 3 );
    assert( ecount( 1, 1 ) == 0 );
    assert( ecount( 2, 2 ) == 1 );
}

答案 12 :(得分:0)

答案:

(max - min + 2 - (max % 2) - (min % 2)) / 2

一个简短的解释:

  • even..even yield(length + 1)/ 2
  • even..odd yield length / 2
  • odd..even yield length / 2
  • odd..odd yield(length - 1)/ 2

  • length = max - min + 1

因此,对于偶数最小值,答案为(length - 1) / 21/2即使最小值加1/2。 请注意,(length - 1) / 2 == (max - min) / 2和“奖金”为(1 - (min % 2)) / 2(1 - (max % 2)) / 2。总结并简化以获得上述答案。

答案 13 :(得分:0)

就开始和长度而言:

(length >> 1) + (1 & ~start & length)

如果开始是偶数且长度是奇数,则

长度的一半加1。

就开始和结束而言:

((end - start + 1) >> 1) + (1 & ~start & ~end)

如果开始是偶数且结束是偶数,则

一半长度加1。

答案 14 :(得分:0)

这根本不需要任何条件:

evencount = floor((max - min)/2) + 1

答案 15 :(得分:-3)

伪代码(我不是C编码器):

count = 0;
foreach(i in range){
    if(i % 2 == 0){
      count++;
    }
}