Что самый простой путь состоит в том, чтобы вычислить количество четных чисел в диапазоне целых чисел без знака?
Пример: если диапазон [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;
РЕДАКТИРОВАТЬ2: Из-за, на мой взгляд, несколько неправильного определения целочисленного деления в C (целочисленное деление усекает вниз для положительных чисел и вверх для отрицательных чисел) эта формула не будет работать, если begin отрицательное нечетное число.
РЕДАКТИРОВАТЬ 3: Пользователь «iPhone новичок» правильно замечает, что если begin% 2
заменить на begin & 1
, это будет работать правильно для всех диапазонов.
Ответ:
(max - min + 2 - (max % 2) - (min % 2)) / 2
Краткое объяснение:
odd..odd дает (длина - 1) / 2
длина = max - min + 1
Следовательно, ответ будет (длина - 1) / 2
плюс 1/2
для четного минимума плюс 1/2
для четного максимума.
Обратите внимание, что (длина - 1) / 2 == (max - min) / 2
, а «бонусы» равны (1 - (min% 2)) / 2
и (1 - (max% 2)) / 2
. Суммируйте все это и упростите, чтобы получить ответ выше.
Псевдокод (я не кодировщик C):
count = 0;
foreach(i in range){
if(i % 2 == 0){
count++;
}
}
Число четных чисел от 0 до n равно [ n ] / 2] + 1. Следовательно, количество четных чисел между ( n + 1) и m равно ([ m / 2] + 1) - ([ n / 2] + 1) = [ m / 2] - [ n / 2].
Для подсчета четных чисел между m и n ответ, следовательно, будет [ m / 2] - [( n ] - 1) / 2].
[x] переводится в направлении - \ infty. Помните, что обычное целочисленное деление C в нашем случае работает неправильно: a / 2
округляется до нуля, а не - \ infty, поэтому результат не будет [ a / 2 ] для случая отрицательного a .
Это должен быть самый простой расчет; работает и с отрицательными числами. (Однако необходимо, чтобы m > = n .) Не содержит if
s и ?:
s.
Если вы не учитываете отрицательные числа, вы можете использовать только m / 2 - (n + 1) / 2 + 1
, иначе floor (m / 2.0) - floor (( n-1) /2.0)
Совет 1. Оператор по модулю вернет остаток от текущего числа
Совет 2: вам не нужен цикл for
Совет 3: диапазон является непрерывным
Совет 4 : Число четных чисел в непрерывном диапазоне составляет половину четных (иногда половина + 1, иногда половина - 1)
Совет 5: Основываясь на Совете 1: подумайте также о том, что (будучи + end + 1)% 2 дает
Подсказка 6: Большинство или все ответы в этой цепочке неверны
Подсказка 7. Обязательно попробуйте решение с отрицательными диапазонами чисел
{{ 1}} Совет 8. Обязательно попробуйте свое решение с диапазонами, охватывающими как отрицательные, так и положительные числа
Я бы сказал
(max - min + 1 + (min % 2)) / 2
Изменить: Эмм, ладно, почему-то я подумал, что (min% 2) возвращает 1 для четных чисел ....: ). Правильная версия -
(max - min + 1 + 1 - (min % 2)) / 2
или, скорее,
(max - min + 2 - (min % 2)) / 2
С точки зрения начала и длины:
( length >> 1) + (1 & ~ start & length)
половина длины плюс 1, если начало четное, а длина нечетная.
В терминах начала и конца:
((end - start + 1) >> 1) + (1 & ~ start & ~ end)
половина длины плюс 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
Это поможет даже для диапазонов с отрицательными числами.
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
А почему бы и нет:
#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 );
}
Диапазон всегда равен [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 - (мин.% 2)
.
int start, stop;
start = 0;
stop = 9;
printf("%d",(stop-start)/2+((!(start%2) || !(stop%2)) ? 1 : 0));
Где start и stop могут содержать любое значение. Нет необходимости повторять, чтобы определить это число.
Это вообще не требует никаких условий:
evencount = floor((max - min)/2) + 1
Первое четное число в диапазоне: (начало + 1) и ~1
(округление начало
до четного числа).
Последнее четные числа в диапазоне: end & ~1
(округление end
до четного числа).
Таким образом, общее число четных чисел в диапазоне составляет: (конец и ~1) - ((начало + 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++;
Надеюсь, это поможет.