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

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

例如:如果范围是[0 … 4]那么答案是3(0,2,4)

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

 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中的整数除法有些不正确的定义(整数除法向下截断正数而向上截断为负数)当start为负奇数时,此公式将不起作用。

编辑3:用户’iPhone初学者’正确观察到如果begin % 2被替换为begin & 1这将适用于所有范围。

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

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

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

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

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

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

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

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

即使对于负数的范围,这也可以解决问题。

 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 

答案是使用二进制AND。

所以数字在0和1的内存中表示。比如说4和5。

4 = 0000 0100

5 = 0000 0101

每个偶数最后都有一个零,每个奇数最后都有1个;

in c’1’表示true,’0’表示false。

所以:让代码;

 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。

这完全有效。

我有点惊讶迭代试图解决这个问题。 一个范围内可能的偶数最小数量等于数字数组长度的一半,或者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 

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

 bd | #even 0 0 | c-a+1 0 1 | c-a+1 1 0 | ca 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)

我会说

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

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

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

更确切地说

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

范围中的第一个偶数是: (begin + 1) & ~1 (round begin to even number)。

范围中的最后一个偶数是: end & ~1 (round end to even number)。

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

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

让我们从逻辑上看一下……

我们有四个案例……

 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++; 

希望这可以帮助。

哦,好吧,为什么不呢:

 #include  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 ); } 

答案:

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

一个简短的解释:

  • 甚至……平均收益率(长度+ 1)/ 2
  • even..odd产生长度/ 2
  • 奇数…甚至产量长度/ 2
  • 奇数…收益率(长度 – 1)/ 2

  • length = max – min + 1

因此,答案是(length - 1) / 2加上1/2甚至最小值加1/2甚至最大值。 注意(length - 1) / 2 == (max - min) / 2 ,“奖励”是(1 - (min % 2)) / 2(1 - (max % 2)) / 2 。 总结并简化以获得上述答案。

在开始和长度方面:

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

如果开始是偶数且长度是奇数,则长度的一半加1。

在开始和结束方面:

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

如果开始是偶数且结束是偶数,则一半长度加1。

这根本不需要任何条件:

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

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

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