2010-04-21 8 views
13

Jaki jest najprostszy sposób obliczenia liczby parzystej w zakresie liczb całkowitych bez znaku?Najprostszy sposób obliczania liczby parzystych w danym zakresie

Przykład: jeśli zakres wynosi [0 ... 4] to odpowiedź brzmi 3 (0,2,4)

Mam twardy czas, aby pomyśleć o wszelkich prosty sposób. Jedyne rozwiązanie, na które wpadłem, zawierało kilka instrukcji if. Czy istnieje prosty wiersz kodu, który może to zrobić bez instrukcji if lub potrójnych operatorów?

+3

Rozmiar zakresie podzielonej przez dwa? –

+0

@Neil, czy nie miałoby to zastosowania tylko, jeśli zakres wynosi zawsze '0..x'? –

+2

Potrzebuje tagu 'praca domowa'? –

Odpowiedz

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

który może być przekształcony:

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

Edycja: ten może ponadto uprościć do:

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

EDIT2: Ze względu na moim zdaniem nieco błędna definicja podziału całkowitej w C (podział całkowitą obcina dół dla liczb dodatnich i ujemnych w górę do liczb) formuła ta nie będzie działać, gdy zacznie to negatywny nieparzysta .

Edit3: użytkownika Początkujący iPhone "słusznie zauważa, że ​​jeśli begin % 2 otrzymuje z begin & 1 to będzie działać poprawnie na wszystkich zakresach.

+0

Nie działa dla przykładu OP, tj. 0..4 powinien powrócić 3. –

+0

@Paul R Błąd Fencepost, naprawiony. –

+0

Wydaje się być w błędzie. Dla podanego przykładu [0..4] 'even = (4 - 0 - (0% 2))/2 = 4/2 = 2'. Myślę, że 'int even = (end - begin - (begin% 2))/2 + 1;' to właściwa odpowiedź – SergGr

-3

kod pseudo (jestem C koder)

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

Pętla to przesada tutaj – SergGr

+2

O (n) jest o wiele za droga (... i brzydka) – Fdr

7

wskazówka 1: Operator modulo powróci pozostałą numer bieżącej
wskazówka 2: nie potrzebują pętli
Wskazówka 3: Zakres jest ciągły
Wskazówka 4: Liczba liczb parzystych w zakresie ciągłym jest równa połowie (czasami połowa + 1, czasami połowa - 1)
Wskazówka 5: W oparciu o podpowiedź 1: Zastanów się także + koniec + 1)% 2 daje
Wskazówka 6: większość lub wszystkie odpowiedzi w tym wątku są błędne
wskazówkę 7: Upewnij się spróbować rozwiązania z liczby ujemnej waha
wskazówka 8: Sprawdź, czy spróbować rozwiązania z zakresów obejmujących zarówno liczby ujemne i dodatnie

+0

, którą znam, ale umieszczenie jej w jasnym zdaniu jest trochę trudne. W zależności od zasięgu mogą występować liczby parzyste n/2 lub n/2 + 1. – Fdr

+0

@Fdr: Zobacz podpowiedź # 1. –

+0

@Fdr: Zastanów się, co by się stało, gdybyś użył go na punkcie końcowym. –

0

Powiedziałbym

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

Edycja: Erm porządku z jakiegoś powodu myślałam, że (min 2%) zwraca 1 dla liczb parzystych .... :). Poprawna wersja to

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

czy raczej

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

Co jeśli 'min' i' max' są zarówno 1? – Arkku

+0

Tak, masz rację, głuptasie. Patrz wyżej. – michalburger1

+0

Nie działa dla (-3, -2) –

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

Gdzie rozpocząć i przystanek może posiadać żadnej wartości. Nie trzeba wykonywać iteracji, aby określić ten numer.

2

Ilość parzystych między 0 i n to [n/2] + 1. W związku z tym liczba parzystych pomiędzy ( n + 1) oraz m oznacza ([m/2] + 1) - ([n/2] + 1) = [m/2] - [n/2].

Dla zliczania parzystych pomiędzy m i n odpowiedź zatem będzie [m/2] - [( n - 1)/2].

[x] zostaje przeniesiony w kierunku - \ infty. Uważaj, że zwykły podział na liczby całkowite nie działa poprawnie w naszym przypadku: a/2 jest zaokrąglany w kierunku zera, nie - \ infty, więc wynik nie będzie [a/2] dla tego przypadku ujemnego a.

To powinno być najprostsze obliczenie; działa również dla liczb ujemnych. (Wymaga jednak, aby m> = n.) Nie zawiera if s oraz ?: s.

Jeśli nie uważają ujemnych wartości, można używać tylko m/2 - (n+1)/2 + 1, poza floor(m/2.0) - floor((n-1)/2.0)

0

zakres jest zawsze [2a + b, 2c + d] i B, D = {0,1}. Stół:

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

Teraz = min/2, b = min% 2, C = maks/2 d = maks% 2.

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

+0

Nie działa dla (-3, -2) –

+0

nie, nie brałem pod uwagę liczb ujemnych , mój błąd –

0

Pierwsza liczba parzysta w zakres wynosi: (begin + 1) & ~1 (runda begin aż do parzystej liczby).

Ostatnia parzysta liczba z przedziału to: end & ~1 (runda end aż do parzystej liczby).

Łączna liczba parzystych liczb w tym zakresie wynosi zatem: (end & ~1) - ((begin + 1) & ~1) + 1.

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

Czy zdefiniowano funkcję ~ 1? Ładny, czysty algorytm, ale nie znam takiej funkcji. –

+0

@Kirk: '~' jest bitowym unarnym operatorem NOT w C/C++. Więc '~ 1' jest int ze wszystkimi bitami oprócz LS ustawionymi na 1. –

0

Spójrzmy na to logicznie ...

Mamy cztery przypadki ...

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 

Pierwsze trzy przypadki mogą być traktowane po prostu jako ...

(1 + last - first)/2 

Czwarty przypadek nie spada już tak ładnie do tego, ale możemy fudge wokół trochę za to dość łatwo ...

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

Nadzieja to pomaga.

2

To wystarczy, nawet dla zakresów z liczbami ujemnymi.

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

Testowane z następującego kodu:

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

wyjściowa:

[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 
0

Och dobrze, to dlaczego nie:

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

Ma sens, ale nie jest to jedna linia kodu z instrukcjami" if ". –

+0

To "najłatwiejsze" rozwiązanie, IMHO - było głównym pytaniem. Nie widzę żadnego możliwego powodu, aby napisać go jako jedno-liniowy. –

+0

@Neil - tu jest ich mnóstwo! Na pewno trzeba być poprawnym! ;) na przykład spróbuj moje. –

0

Odpowiedź:

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

Krótki Opis:

  • even..even wydajności (długość + 1)/2
  • długość wydajności even..odd/2
  • odd..even długości plonów/2
  • wydajności odd..odd (długość - 1)/2

  • długość = max - min + 1

Dlatego odpowiedź brzmi: (length - 1)/2 plus 1/2 dla parzystej min plus 1/2 dla parzystej maks. Uwaga: (length - 1)/2 == (max - min)/2, a "bonusy" to (1 - (min % 2))/2 i (1 - (max % 2))/2. Zsumuj to wszystko i uprość, aby uzyskać powyższą odpowiedź.

+0

Nie działa w przypadku wykluczeń, np. (-3, -2). –

+0

Dobrze. Powinno to być: (max - min + 2 - (abs (max)% 2) - (abs (min)% 2))/2. – Bolo

+0

Z drugiej strony, pytanie wyraźnie określa "zakres liczb całkowitych bez znaku". – Bolo

1

Jestem nieco zaskoczony, że próbowano rozwiązać ten problem. Minimalna liczba liczb parzystych możliwych w zakresie jest równa połowie długości tablicy liczb lub, rangeEnd - rangeStart.
Dodaj 1, jeśli pierwsza lub ostatnia liczba jest parzysta.

więc metoda jest: (przy użyciu 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 
+3

Twoje testy dzielą się na 2, ale Twoja formuła w ogóle nie zawiera podziału. –

+1

Masz rację, powinien powiedzieć Math.floor ((rangeEnd - rangeStart)/2) Dzięki – souLTower

0

chodzi o początek i długość:

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

połowa długości oraz 1 jeśli start jest nawet i długość jest nieparzysta.

chodzi o początek i koniec:

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

połowa długości oraz 1 czy początek i koniec jest nawet nawet.

+0

Jestem trochę dumny z użycia bitowego I jako warunkowego. :) –

0

ta nie wymaga żadnych warunków na wszystkich:

evencount = floor((max - min)/2) + 1 
Powiązane problemy