Systemy liczbowe, rozmiary w bajtach i jednostki, o które ludzie się spierają
Zapisana liczba niesie dwie rzeczy: wartość oraz zestaw założeń co do sposobu jej odczytu. 0xFF, 255, 0o377 i 11111111 to jedna wielkość w czterech notacjach. Terabajt i tebibajt różnią się o dziesięć procent. 1,234 to mniej więcej tysiąc w Londynie i mniej więcej jeden w Berlinie. Większość błędów liczbowych bierze się z założeń, a nie z arytmetyki.
System dwójkowy, ósemkowy, dziesiętny i szesnastkowy
Każdy system pozycyjny działa tak samo. Każda pozycja jest warta podstawę razy pozycję po jej prawej, a cyfry biegną od zera do podstawy minus jeden. Podstawa 16 potrzebuje sześciu dodatkowych cyfr, więc pożycza A do F na wartości od dziesięciu do piętnastu.
Zapisu szesnastkowego używa się do bajtów i kolorów, ponieważ 16 to 2 do potęgi 4, więc jedna cyfra szesnastkowa to dokładnie cztery bity, a jeden bajt to dokładnie dwie cyfry szesnastkowe, bez żadnych przeniesień między nimi.
0 0000 4 0100 8 1000 C 1100
1 0001 5 0101 9 1001 D 1101
2 0010 6 0110 A 1010 E 1110
3 0011 7 0111 B 1011 F 1111
Ta tabelka to cała konwersja. Żeby przejść z zapisu szesnastkowego na dwójkowy, zastąp każdą cyfrę jej czterema bitami: 0x2F staje się 0010 1111. Żeby wrócić, pogrupuj bity po cztery od prawej strony, dopełniając z lewej zerami, i odczytaj każdą grupę z tabelki.
Dla systemu dziesiętnego użyj wag pozycji. 0x2F to 2 x 16 + 15, czyli 47. W drugą stronę dziel wielokrotnie przez 16 i odczytaj reszty od dołu do góry:
200 / 16 = 12 remainder 8 -> 8
12 / 16 = 0 remainder 12 -> C
200 decimal = 0xC8
System ósemkowy pakuje trzy bity na cyfrę i dlatego uprawnienia w Uniksie zapisuje się jako 755: każda cyfra to jedna trójka rwx, gdzie 7 to 111, a 5 to 101. Kolor CSS taki jak #FF8800 to trzy bajty, po jednym na kanał, każdy biegnący od 0 do 255, a skrócony zapis trzycyfrowy #F80 rozwija się przez podwojenie każdej cyfry, a nie przez dopełnienie zerami. Konwerter systemów liczbowych obejmuje wszystkie cztery podstawy naraz.
Kod uzupełnień do dwóch i skąd biorą się zakresy
Bajt mieści 256 różnych wzorców. Odczytane bez znaku dają zakres od 0 do 255. Odczytane ze znakiem mają najstarszy bit oznaczający połowę ujemną, a wartość ujemna to jej wzorzec minus 256. Ten schemat to kod uzupełnień do dwóch, wybrany dlatego, że zwykłe dodawanie dwójkowe działa wtedy identycznie na wartościach ze znakiem i bez znaku.
Żeby zanegować liczbę, odwróć każdy bit i dodaj jeden. Zakres jest niesymetryczny, ponieważ zero zajmuje jedno ze 128 miejsc w połowie nieujemnej, więc bajt ze znakiem biegnie od -128 do 127. Dodanie jedynki do górnego krańca zakresu zawija do dolnego:
0111 1111 127
+ 0000 0001 1
= 1000 0000 -128
W większości języków nic nie jest przy tym sygnalizowane; wartość po prostu pojawia się po drugiej stronie zakresu. To samo zawinięcie przy 32 bitach jest problemem roku 2038, w którym 32 bitowy znacznik czasu Unix ze znakiem kończy się na 2 147 483 647 sekundach. Szesnaście bitów bez znaku daje zakres od 0 do 65 535 i właśnie dlatego numery portów TCP kończą się w tym miejscu, a generator losowych portów losuje z tego zakresu, omijając porty zarezerwowane poniżej 1024.
Kilobajty, kibibajty i brakujące gigabajty
Producenci nośników liczą w potęgach dziesiątki. Systemy operacyjne historycznie liczyły w potęgach dwójki i opatrywały wynik przedrostkiem dziesiętnym, i tu zaczyna się spór. Przedrostki binarne (KiB, MiB, GiB) istnieją po to, żeby usunąć tę niejednoznaczność.
| Potęga dziesiątki | Wartość dziesiętna | Przedrostek binarny | Wartość binarna | Różnica |
|---|---|---|---|---|
| kB, 10^3 | 1,000 | KiB, 2^10 | 1,024 | 2.4% |
| MB, 10^6 | 1,000,000 | MiB, 2^20 | 1,048,576 | 4.9% |
| GB, 10^9 | 1,000,000,000 | GiB, 2^30 | 1,073,741,824 | 7.4% |
| TB, 10^12 | 1,000,000,000,000 | TiB, 2^40 | 1,099,511,627,776 | 10.0% |
| PB, 10^15 | 10^15 | PiB, 2^50 | 1,125,899,906,842,624 | 12.6% |
Dysk o pojemności 1 TB mieści 10^12 bajtów w postaci, w jakiej jest sprzedawany. Podziel to przez 2^30, a otrzymasz 931,32, więc Windows raportuje około 931 GB, używając etykiety dziesiętnej dla wielkości binarnej. Nic nie brakuje; te same bajty są dzielone przez inną liczbę. macOS i większość narzędzi linuksowych raportują dziś gigabajty dziesiętne, co zgadza się z pudełkiem. Rozmiary pamięci są naprawdę binarne, więc 16 GB pamięci RAM to faktycznie 16 GiB.
Prędkości sieciowe liczy się w bitach, a nie w bajtach, i zawsze dziesiętnie. Łącze 100 Mbps przenosi 100 000 000 bitów na sekundę, czyli 12,5 MB na sekundę przed narzutem. Narzut protokołów zabiera kilka procent, więc realnym sufitem jest od 11 do 12 MB na sekundę. Szybkim sprawdzeniem jest podzielenie reklamowanej wartości w megabitach przez osiem, a konwerter jednostek obejmuje jednostki pojemności.
Liczby zmiennoprzecinkowe i dlaczego pieniądze nie są liczbą zmiennoprzecinkową
Ułamki dwójkowe potrafią przedstawiać wyłącznie sumy połówek, ćwiartek, ósemek i tak dalej. Jedna dziesiąta nie ma dokładnej postaci dwójkowej, tak jak jedna trzecia nie ma dokładnej postaci dziesiętnej, więc 0.1 zapisane jako liczba podwójnej precyzji IEEE 754 jest odrobinę większe niż jedna dziesiąta. Dodaj dwa takie przybliżenia, a błąd wypłynie na wierzch:
0.1 + 0.2 = 0.30000000000000004
Liczba podwójnej precyzji ma 53 bity mantysy. Dzięki temu każda liczba całkowita do 2^53 (9 007 199 254 740 992) jest przedstawiana dokładnie, podobnie jak każdy ułamek, którego mianownik jest potęgą dwójki. Powyżej 2^53 odstęp między przedstawialnymi wartościami wynosi 2, więc 2^53 + 1 równa się 2^53. Właśnie dlatego 64 bitowe identyfikatory bazodanowe przesyłane przez JSON powinny podróżować jako ciągi znaków: liczby w JavaScript są liczbami podwójnej precyzji, a 19 cyfrowy identyfikator po cichu gubi końcowe cyfry.
Dla pieniędzy przechowuj całkowite jednostki podrzędne (grosze, centy) albo używaj typu dziesiętnego działającego w podstawie dziesiątkowej. Nigdy nie porównuj liczb zmiennoprzecinkowych na równość; porównuj różnicę z małą tolerancją. Kalkulator wyrażeń również pracuje na liczbach podwójnej precyzji i dziedziczy te same ograniczenia.
Zaokrąglanie i zaokrąglanie dwa razy
Zaokrąglanie połówek w górę odsyła remis w stronę od zera. Zaokrąglanie połówek do parzystych, zwane też zaokrąglaniem bankierskim, odsyła remis do najbliższej cyfry parzystej, co usuwa obciążenie w górę, jakie zaokrąglanie połówek w górę wprowadza w długiej kolumnie liczb. Jest to ustawienie domyślne IEEE 754 i reguła w kilku standardach rachunkowości.
| Wartość | Połówki w górę | Połówki do parzystych |
|---|---|---|
| 0.5 | 1 | 0 |
| 1.5 | 2 | 2 |
| 2.5 | 3 | 2 |
| 3.5 | 4 | 4 |
| -0.5 | -1 | 0 |
Zaokrąglaj raz, wychodząc od wartości pierwotnej. Zaokrąglenie 2,4449 do trzech miejsc po przecinku daje 2,445, a zaokrąglenie tego do dwóch daje 2,45, podczas gdy zaokrąglenie wartości pierwotnej wprost do dwóch daje 2,44. Łańcuchowe zaokrąglanie przez kolumny pośrednie jest częstym źródłem sum rozjeżdżających się o grosz. Pokrewna niespodzianka: 2,675 zaokrągla się w większości języków do 2,67, ponieważ zapisana liczba podwójnej precyzji to 2,67499999999999982.
Procent i punkt procentowy
Wskaźnik przesuwający się z 4% na 5% wzrósł o jeden punkt procentowy albo o 25% w ujęciu względnym. Oba stwierdzenia są poprawne i jednostkę trzeba podać.
Zmiany procentowe się nie znoszą. Spadek o 50%, po którym następuje wzrost o 50%, zostawia 75, a nie 100, ponieważ drugi procent jest liczony od mniejszej podstawy. Odrobienie spadku o p wymaga wzrostu o p / (1 - p), więc spadek o 50% wymaga 100%, a spadek o 80% wymaga 400%. Kolejne zmiany się mnożą, tworząc ciąg geometryczny, a nie sumę, i taki właśnie wzrost modeluje generator sekwencji liczb.
Zmiana ze starej wartości na nową to (new - old) / old x 100, i to właśnie kalkulator procentów podaje jako różnicę. Usunięcie 20% podatku VAT oznacza dzielenie przez 1,2, a nie odejmowanie 20%. Uśrednianie procentów po grupach o różnej wielkości daje błędny wynik ogólny, chyba że średnia jest ważona, a narzędzie sumy i średniej, pokazując medianę obok średniej, uwidacznia skośność.
Liczby sformatowane pod ustawienia regionalne
Formatowanie jest decyzją prezentacyjną i nie da się go odwrócić bez znajomości ustawień regionalnych. 1.234 to jeden z kawałkiem w Wielkiej Brytanii i tysiąc w Niemczech. 1,234 odwrotnie. Niektóre ustawienia grupują cyfry spacją albo apostrofem.
| Ustawienia regionalne | 1234567.89 |
|---|---|
| en-GB, en-US | 1,234,567.89 |
| de-DE | 1.234.567,89 |
| fr-FR | 1 234 567,89 |
| de-CH | 1'234'567.89 |
| en-IN | 12,34,567.89 |
Grupowanie indyjskie stawia pierwszy separator po trzech cyfrach, a każdy kolejny co dwie cyfry, dając lakh i crore zamiast tysięcy i milionów. Parsowanie sformatowanego ciągu znaków z powrotem na liczbę jest właśnie z tego powodu stratne, więc przechowuj i przesyłaj wartości niesformatowane, z kropką jako separatorem dziesiętnym, a formatuj dopiero w miejscu wyświetlenia. Tam, gdzie liczba musi być dla czytającego jednoznaczna, zwykłym podejściem jest wypisanie jej słownie, co robi zamiana liczby na słowa, stosowana na czekach i w umowach. Liczby rzymskie stoją poza tym wszystkim: bez wartości pozycyjnej i bez zera konwerter liczb rzymskich obsługuje raczej system karbowy niż podstawę.