Ostatnio natknąłem się na ten idiom programowania:
const float Zero = 0.0;
który jest następnie wykorzystywany w porównaniach:
if (x > Zero) {..}
Czy ktoś może wyjaśnić, czy jest to naprawdę bardziej wydajne, czytelne lub możliwe do utrzymania niż:
if (x > 0.0) {..}
UWAGA: Mogę wymyślić inne powody, by zdefiniować tę stałą. Zastanawiam się tylko nad jej użyciem w tym kontekście.
x
ma typfloat
,x > 0.0
wymusza awans dodouble
, który może być mniej wydajny. To nie jest dobry powód, aby korzystać nazwany stałą jednak tylko dla upewniając się swoimi stałymi mieć odpowiedni typ (np0f
,float(0)
lubdecltype(x)(0)
).13.37
nie jestfloat
, to jestdouble
. Więc jeśli chciałeś,float
to możliwe, że twój nauczyciel miał rację. W niektórych kontekstach (np. Przypisanie do liczby zmiennoprzecinkowej)13.37
zostanie domyślnie przekonwertowane nafloat
żądany, aw innych kontekstach (np. Dedukcja typu szablonu) nie będzie, podczas gdystatic const float
zawsze zaczyna się zgodnie z zamierzonym typem. Dlatego bardziej bezpieczny dla typu. Pamiętaj, że tak też będzie13.37f
! Istnieją jednak inne powody do unikania makra niż „bezpieczeństwo typu”, więc równie prawdopodobne jest, że korepetytor przedstawił ci kiepską argumentację.Odpowiedzi:
Możliwe przyczyny to buforowanie, nazywanie lub wymuszanie
Buforowanie (nie dotyczy)
Chcesz uniknąć kosztów utworzenia obiektu podczas aktu porównania. W Javie przykładem może być
wiąże się to z dość ciężkim procesem tworzenia i jest lepiej obsługiwany przy użyciu dostarczonej metody statycznej:
Pozwala to na porównania bez ponoszenia powtarzających się kosztów tworzenia, ponieważ BigDecimal jest wstępnie buforowany przez JVM podczas inicjalizacji.
W przypadku tego, co opisałeś, prymityw wykonuje tę samą pracę. Jest to w dużej mierze zbędne pod względem buforowania i wydajności.
Nazewnictwo (mało prawdopodobne)
Pierwotny programista próbuje zapewnić jednolitą konwencję nazewnictwa dla wspólnych wartości w całym systemie. Ma to pewne zalety, szczególnie w przypadku rzadkich wartości, ale coś tak podstawowego, jak zero, jest tego warte tylko w przypadku wcześniejszej pamięci podręcznej.
Rodzaj wymuszenia (najprawdopodobniej)
Pierwotny programista próbuje wymusić określony typ pierwotny, aby upewnić się, że porównania są rzutowane na ich poprawny typ i ewentualnie na określoną skalę (liczbę miejsc dziesiętnych). Jest to w porządku, ale prosta nazwa „zero” jest prawdopodobnie niewystarczająco szczegółowa dla tego przypadku użycia, a ZERO_1DP jest bardziej odpowiednim wyrażeniem zamiaru.
źródło
typedef
spowoduje, że typ zmiennej będzie dokładnie w jednym miejscu i umożliwi jej zmianę bez konieczności zmiany kodu.0.0f
.byteVar1 = byteVar2 Or CB128
wydaje się trochę ładniejsze niżbyteVar1 = byteVar2 Or CByte(128)
. Oczywiście, posiadanie odpowiedniego przyrostka liczbowego dla bajtów byłoby jeszcze lepsze. Ponieważ C # promuje operandy bitowe do operatorów,int
nawet jeśli wynik byłby w stanie zmieścić się wbyte
, problem nie jest tak istotny.To z powodu „dręczenia narzędzi”
Możliwym powodem, którego nie wymieniono tutaj, jest to, że wiele wysokiej jakości narzędzi oznacza użycie magicznych liczb . Często złym zwyczajem jest wrzucanie do algorytmu liczb magicznych bez ich wyraźnego widocznego do późniejszego wprowadzenia zmian, szczególnie jeśli są one duplikowane w wielu miejscach w kodzie.
Tak więc, chociaż narzędzia te mają rację w kwestii zgłaszania takich problemów, często generują fałszywe alarmy w sytuacjach, w których te wartości są nieszkodliwe i najprawdopodobniej są statyczne lub po prostu są wartościami inicjalizacyjnymi.
A kiedy tak się dzieje, czasami stajesz przed wyborem:
O wydajności
To chyba zależy od języka, ale jest to dość powszechne w Javie i nie ma wpływu na wydajność, ponieważ wartości są wstawiane w czasie kompilacji, jeśli są rzeczywistymi stałymi
static final
. Nie miałoby to wpływu na C lub C ++, jeśli zostaną zadeklarowane jako stałe lub nawet jako makra preprocesorów.źródło
Może to mieć sens, ponieważ wyraźnie określa,
Zero
że jest typufloat
.Przynajmniej w C i C ++ wartość
0.0
jest typudouble
, podczas gdy jej odpowiednikiemfloat
jest0.0f
. Więc zakładanie,x
że porównujesz, jest zawszefloat
powiedzeniema jednocześnie promować,
x
abydouble
dopasować do rodzaju,0.0
który może prowadzić do problemów (szczególnie z testami równości). Porównanie bez konwersji byłoby oczywiścieco robi to samo co
Niemniej jednak myślę, że znacznie bardziej użyteczne byłoby włączenie ostrzeżeń o konwersjach w kompilatorze zamiast zmuszania użytkowników do pisania niezręcznego kodu.
źródło
Po pierwsze, zero definiuje się jako
float
, a nieint
. Oczywiście nie ma to wpływu na porównanie, ale w innych przypadkach, gdy używana jest ta stała, może to mieć znaczenie.Nie widzę innego powodu, dla którego zostałby
Zero
tutaj ogłoszony stałym. To tylko styl kodowania i lepiej jest podążać za tym stylem, jeśli jest używany wszędzie indziej w tym programie.źródło
Jest prawie na pewno dokładnie tak samo wydajny podczas wykonywania (chyba że twój kompilator jest bardzo prymitywny) i bardzo nieznacznie mniej wydajny podczas kompilacji.
Jeśli chodzi o to, czy jest to bardziej czytelne niż
x > 0
... pamiętaj, że są ludzie, którzy szczerze, szczerze sądzą, że COBOL był świetnym pomysłem i przyjemnością z nim współpracować - a potem są ludzie, którzy myślą dokładnie tak samo o C. (Plotka głosi, że że istnieją nawet programiści o takiej samej opinii na temat C ++!) Innymi słowy, nie osiągniesz ogólnej zgody w tej kwestii i prawdopodobnie nie warto o to walczyć.źródło
Jeśli piszesz ogólny (tj. Nieswoisty dla kodu) kod, to bardzo możliwe.
zero()
Funkcja może mieć zastosowanie do wszelkich algebraicznych typu lub dowolnego typu, który jest dodatkiem grupa wrt. Może to być liczba całkowita, może być wartością zmiennoprzecinkową, może nawet być funkcją, jeśli twoja zmienna jest, powiedzmy, funkcją w jakiejś przestrzeni liniowej (np. X jest funkcją liniową postaci z -> a_x * z + b_x), a następniezero()
udostępnia funkcję, przy czym oba a i b sązero()
typu podstawowego.Można by się spodziewać takiego kodu w, powiedzmy, C ++, być może (chociaż
zero()
nie jest to bardzo powszechny AFAIK), lub w Julii i być może w innych językach.źródło