2009-11-07 11 views
9

Po zwiększeniu zaangażowania w szkolenie nowych inżynierów i czytanie Jon Skeet's DevDays presentation zacząłem rozpoznawać wielu inżynierów, nie są jasne, kiedy używać, które numeryczne typy danych, gdy. Doceniam rolę, jaką odgrywa formalny stopień naukowy w udzielaniu pomocy, ale widzę wielu nowych inżynierów, którzy wykazują niepewność, ponieważ nigdy nie pracowali z dużymi zbiorami danych, oprogramowaniem finansowym, programowaniem problemów z fyisem lub statystyką lub złożonymi problemami z datastore. .Używanie odpowiedniego typu danych numerycznych

Moje doświadczenie jest takie, że ludzie naprawdę gubią pojęcia, gdy są wyjaśnione w kontekście. Szukam dobrych przykładów prawdziwych problemów programistycznych, w których niektóre dane są najlepiej reprezentowane za pomocą typu danych. Staraj się trzymać z daleka od przykładów podręczników, jeśli to możliwe. Ja tagging to z Java, ale czuć się swobodnie dać przykłady w innych językach i zmieniać tagów:

Integer, Long, Pokój, pływak, BigInteger, etc ...

Odpowiedz

26

Naprawdę nie sądzę, że potrzebujesz przykładów lub czegoś skomplikowanego. To jest proste:

  • Czy to liczba całkowita?
    • Czy może być> 2^63? BigInteger
    • Czy może być> 2^31? długi
    • W przeciwnym razie int
  • Czy jest to liczba dziesiętna?
    • Czy przybliżona wartość jest ok?
      • podwójne
    • Czy to musi być dokładnie? (Przykład: kwoty pieniężne!)
      • BigDecimal

(Kiedy mówię ">", to znaczy "większy w wartości bezwzględnej", oczywiście). Nigdy nie użyłem bajtu ani znaku do przedstawienia liczby, a ja nigdy nie użyłem krótkiego okresu. To od 12 lat programowania w języku Java. Pływak? Meh. Jeśli masz dużą tablicę i masz problemy z pamięcią, tak myślę.

Należy pamiętać, że BigDecimal jest w pewnym sensie błędnie nazwany; twoje wartości nie muszą być duże, aby je potrzebować.

+4

Naprawdę podoba mi się sposób, w jaki go złamałeś. 100% zgadza się z tobą na char, short i Floats z Javą. – Scanningcrew

+0

Jedna dodatkowa wskazówka: Jeśli jest to liczba dziesiętna i musi być dokładna, ale maksymalna liczba miejsc dziesiętnych jest znana z góry (np. Z wartościami $: 2 dec. Miejsca), wtedy możesz po prostu użyć int/long, i dziel na wyjściu. Pozwala to uniknąć problemów z BitDecimalem (wydajność, niewygodne operatory). – sleske

4

BigDecimal jest najlepszy, jeśli chodzi o utrzymanie dokładne obliczenia zmiennoprzecinkowe i możliwość określenia pożądanej dokładności. Uważam, że pływanie (i do pewnego stopnia podwójne) oferuje korzyści wydajnościowe w porównaniu z BigDecimal, ale kosztem dokładności i użyteczności.

+0

+1 do odparcia niektórych idiota, którzy głosowali tę odpowiedź – kar

+0

LOL, dziękuję! –

1

zwykle numeryczną, gdy mówimy independenat urządzenia (32/64-bitowy) Rodzaj dane są poniżej

całkowitą 4 bajty

długości 8 bajtów

dziesiętny/float: 4bytes

podwójne: 8bytes

i rozmiary zmniejszona do połowy wartości ze znakiem (na przykład: dla 4bytes, unsigned = 4billions podpisane = 2billions)

bigInt (w zależności od implementacji języka) czasami do 10 bajtów.

do archiwizacji danych o dużej objętości (np. Wyszukiwarka) zdecydowanie zaleca bajt i zwarcie, aby zaoszczędzić miejsca.

bajt 1 bajt (0-256 niepodpisany, -128 - 128 podpisane)

skrócie: 2 bajt (65k unsigned)


powiedzmy chcesz zapisać rekord o wiek, ponieważ nikt nigdy nie ma więcej niż 150 lat, więc używałeś danych typu BYTE (czytaj powyżej dla rozmiaru), ale jeśli używasz INTEGER, już zmarnowałeś dodatkowe 3 bajty i poważnie powiedziałeś mi, że żyję ponad 4 miliardy lat.

+1

Klasyczny przykład przedwczesnej optymalizacji ... O ile nie zapisujesz OGROMNEJ tablicy lub bazy danych ludzi w wieku USE INT. Nie ma minusów, jeśli rozmiar nie jest problemem (a w większości współczesnych przypadków tak nie jest), a zaletą jest to, że nie należy się modlić do głupich błędów, takich jak błąd Y2K z powodu przedwczesnej optymalizacji. –

+0

mówiłem o AGE, nie o randze lol. weź pod uwagę tematy, które stworzyłem, rozwijam niestandardową wyszukiwarkę w sieci (niestandardowy wysoce zoptymalizowany format indeksu) przez prawie 2 lata i ufajcie, że indeksy stron internetowych to wielka sprawa, jeśli chodzi o optymalizację miejsca na dysku. i używam daty INT (32) i LONG (64), aby zaoszczędzić miejsce i uniknąć limitów Y2K. – kar

+0

również tylko FYI, przechowujemy niektóre z naszych danych w 3 bajtach i 5 bajtach, ładujemy do pamięci w normalnych 4/8 bajtach, aby uzyskać maksymalną efektywność przestrzeni zamiast VInt (lucene) dla dodatkowej szybkości podczas ładowania. Więc tak, wiem, o czym mówię. – kar

4

Jednym z ważnych punktów, które możesz chcieć wypowiedzieć, jest to, że prawie zawsze błędem jest porównywanie liczb zmiennoprzecinkowych dla równości. Na przykład następujący kod jest bardzo prawdopodobne, że nie:

double euros = convertToEuros(item.getCostInDollars()); 
if (euros == 10.0) { 
    // this line will most likely never be reached 
} 

Jest to jeden z wielu powodów, dla których chcesz używać numerów dyskretne do reprezentowania waluty.

Kiedy absolutnie musisz porównać liczby zmiennoprzecinkowe, możesz to zrobić tylko w przybliżeniu; coś do tego stopnia:

double euros = convertToEuros(item.getCostInDollars()); 
if (Math.abs(euros - 10.0) < EPSILON) { 
    // this might work 
} 

Jeśli chodzi o praktyczne przykłady, mój zwykle zasada jest coś takiego:

  • podwójnie: myśleć długo i ciężko przed użyciem; czy ten ból jest tego wart?
  • pływak: nie używaj go
  • bajt: najczęściej używane jako byte [] do reprezentowania kilka surowych danych binarnych
  • int: to jest twoim najlepszym przyjacielem; użyj go do reprezentowania większości rzeczy
  • długa: użyj tego dla znaczników czasu i identyfikatorów bazy danych
  • BigDecimal and BigInteger: jeśli wiesz o nich, są szanse, że wiesz już, co robisz, więc nie potrzebujesz mojej porady

Zdaję sobie sprawę, że nie są to strasznie naukowe zasady, ale jeśli twoja grupa docelowa nie jest informatykiem, najlepiej będzie trzymać się podstaw.

+0

Nie jestem wielkim fanem twojego kodu przykładowego, ponieważ nie powinieneś używać podwójnych danych monetarnych na początek. Powinieneś użyć BigDecimal. Zobacz np. to: http://stackoverflow.com/questions/965831/how-to-parse-a-currency-amount-us-or-eu-to-float-value-in-java/965858#965858 i Item 48 w książka Efektywna Java (edycja 2). – Jonik

+2

Jonik - pokazuje nam, dlaczego podwójne jest złe. A on mówi: "Oto jak to zrobić * jeśli absolutnie musisz * używać zmiennoprzecinkowej". Tu nie ma faulu. –

+0

btw, myślę, że jest to doskonała odpowiedź, przynajmniej tak dobra jak moja. jedynym wyjątkiem jest to, że BigDecimal naprawdę powinien być poproszony jako jedyny sposób precyzyjnego obchodzenia się z liczbami dziesiętnymi; nie tylko "no, pewnie wiesz, co robisz ..". –

1

VInt w Lucene to diabeł. Niewielka przewaga pod względem wielkości jest znacznie ważniejsza od kary za wydajność w czytaniu bajt po bajcie.

Dobrą rzeczą, o której można porozmawiać, jest wymiana przestrzeni w czasie. Oszczędność 200MB była świetna w 1996 roku, ale w 2010 roku burzenie buforów IO czytających bajt w tym samym czasie jest straszne.

Powiązane problemy