Naprawdę krótko, jak napisać poniższy kod inaczej nie wykorzystując modulo (%)?
public static class IntEx { public static bool IsEven(this int value) { return value % 2 == 0; } public static bool IsOdd(this int value) { return !value.IsEven(); } }
Aha, nie chodzi o rozbicie metod na klasy, extension methods itp. :)
public static class IntEx
{
public static bool IsEven(this int value)
{
return (value & 1) == 0;
}
public static bool IsOdd(this int value)
{
return (value & 1) == 1;
}
}
Z testow ktore wykonalem to rozwiazanie jest o jakies 5% szybsze. Dodatkowo w twojej wersji IsOdd wykonuje jedno operacje wiecej, zaprzeczenie IsEven().
no i jaki jest sens robienia chanllenge :) Wlasnie o to mi chodzilo. brawo :)
Male wytlumaczenie dla tych, ktorzy by sie zastanawiali dlaczgeo & 1 dziala. Jest to tak naprawde zrobienie operacji logicznego and na ostatnim bitcie liczby. Jezeli nasza licza to 10 czyli: 1010 w systemie binarnym to mamy
1010 (10)
0001 AND (1)
0000 =
dla liczby 11 (1011):
1011 (11)
0001 AND (1)
0001 =
wiec za pomoca & mozemy napisac kod sprawdzajacy czy liczba jest parzysta lub nie parzysta troche szybciej niz wykorzystujac modulo.
Ja szczerze mam nadzieję, że nikt się nie zastanawia dlaczego to działa. To są podstawy podstaw…oraz oczywista oczywistość :)
Pozdrawiam,
Paweł
A ja mam szczerą nadzieję, że nikomu nie przychodzi do głowy tak pisać, chyba że jest to najczęściej wywoływana funkcja, która po prostu musi być super hiper w kosmos wydajna.
Oj. Z tymi slowami to bym uwazal. Wczoraj poruszalem ten temat ze znajomymi "koderami" i kilku z nich nie potrafilo powiedziec do czego dokladnie sluzy operator &. Sczerze mowiac w pracy jedyne zastosowanie do tego operatora znalazlem w maskowaniu enumeracji (nic wiecej nie przychodzi mi do glowy). Ale zeby tak wogole nie wiedziec jak to dziala to chyba troche wstyd :D
Może i wstyd, ale ja mimo iż wiem jak to działa, to wolałbym nie widzieć takiego kodu. Dla mnie 90% wartości kodu to jego czytelność, a zdecydowanie prościej czyta mi się rozwiązanie, które Gutek napisał w treści tego zadania.
Inna sprawa tutaj jest taka, że akurat te funkcje są skrajnie proste i nazwy są oczywiste, więc pewnie nawet bym nie zajrzał, ale równocześnie takie pisanie powoduje, że programiści mają ochotę pisać tak gdzie indziej, a ja mam ochotę udusić za każdym razem jak coś takiego czytam.
Można jeszcze tak (jak ktoś chciałby inaczej niż powyżej ;))
Tak czy siak operacja na bitach piwinna być najszybsza i też tak bym napisał ;)
[…]
public static bool IsEven(this int value)
{
var remainder =0;
Math.DivRem(value, 2, out remainder);
return remainder == 0;
}
[…]
Reflector powiada ze Math.DivRem korzsta z modulo:
public static int DivRem(int a, int b, out int result)
{
result = a % b;
return (a / b);
}
No tak nie pomyślałem o Reflectorze. Chciałem coś innego pokazać, a tu klops… :)
No operatora & ja używam do … tworzenia wszystkich podzbiorów danego zbioru :)
Nie znam zbytnio C# (tylko podstawy), ale wygląda to mniej więcej tak:
const int elements = 10;
for(int i = 0; i < pow(2.0f, n) – 1; ++i){
for(int j = 0; j < elements; ++j)
if(j & i) write(j);
write("n");
}
W C# warunek nie zadziala, wynik dzialania typA & typB daje typA, wiec w tym przypadku if dla int nie zadziala. Ale chyba chodzilo o to:
for (int i = 0; i < Math.Pow(2.0f, n) – 1; ++i)
{
for (int j = 0; j < elements; ++j)
if ((j & i) == i) Console.Write(j);
Console.WriteLine();
}
faktycznie w C# trzeba jawnie definiować warunki (nie to co c++), ale się rozpędziłem i zły kod dałem warunek powinien być taki :
if( i & (1 << j) == 1)
1 << j to przesunięcie bitowe (nie wiem czy w C# jest), czyli 2 do potęgi j
jak najbardziej w C# tez sa przesuniecia bitowe, nie ma tylko operacji dostepnej w Java >>> Unsigned right shift.
Comments are closed.