Dlaczego Java ma prymitywy dla liczb o różnych rozmiarach?

20

W Javie istnieją prymitywne typy na byte, short, inta longi to samo dla floati double. Dlaczego osoba musi ustawić, ile bajtów należy użyć dla wartości pierwotnej? Czy nie można dynamicznie określić rozmiaru w zależności od tego, jak duża była przekazywana liczba?

Są dwa powody, dla których mogę myśleć:

  1. Dynamiczne ustawienie rozmiaru danych oznaczałoby, że musiałaby również istnieć możliwość dynamicznej zmiany. Może to potencjalnie powodować problemy z wydajnością?
  2. Być może programista nie chciałby, aby ktoś mógł użyć liczby większej niż określony rozmiar, co pozwala mu to ograniczyć.

Nadal uważam, że można wiele zyskać, używając pojedynczego inti pojedynczego floattypu. Czy był jakiś konkretny powód, dla którego Java zdecydowała się nie iść tą drogą?

yitzih
źródło
4
Do downvoters dodam, że to pytanie jest powiązane z pytaniem, na które badacze kompilatora chcą odpowiedzieć .
rwong
Więc jeśli dodałeś do liczby, uważasz, że typ powinien być dynamicznie zmieniany? Czy w ogóle chcę zmienić typ? Jeśli liczba jest inicjowana jako intUnknown alfa = a + b; dostajesz to byłoby trochę trudne dla kompilatora. Dlaczego jest to specyficzne dla java?
paparazzo
@Paparazzi Istnieją istniejące języki programowania i środowiska wykonawcze (kompilatory, interpretery itp.), Które przechowują liczbę całkowitą o dynamicznej szerokości w zależności od tego, jak duża jest rzeczywista wartość (np. Wynik operacji dodawania). Konsekwencje są następujące: kod do wykonania na CPU staje się bardziej skomplikowany; rozmiar tej liczby całkowitej staje się dynamiczny; odczytanie liczby całkowitej szerokości dynamicznej z pamięci może wymagać więcej niż jednego wyłączenia; Struktury (obiekty) i tablice zawierające liczby całkowite o dynamicznej szerokości wewnątrz swoich pól / elementów również mogą mieć rozmiar dynamiczny.
rwong
1
@tofro Nie rozumiem. Po prostu wyślij liczbę w dowolnym formacie: dziesiętnym, binarnym itp. Serializacja jest kwestią całkowicie ortogonalną.
ogrodnik
1
@gardenhead To jest ortogonalne, tak, ale ... po prostu rozważ przypadek, w którym chcesz komunikować się między serwerem napisanym w Javie a klientem napisanym w C. Oczywiście można to rozwiązać za pomocą dedykowanej infrastruktury. Np. Istnieją rzeczy takie jak developers.google.com/protocol-buffers . Jest to jednak duży młot do drobnej nakrętki przenoszenia liczby całkowitej przez sieć. (Wiem, że nie jest to mocny argument, ale może warto rozważyć - omówienie szczegółów wykracza poza zakres komentarzy).
Marco13

Odpowiedzi:

16

Podobnie jak wiele innych aspektów projektowania języka, dochodzi do kompromisu elegancji z wydajnością (nie wspominając o historycznych wpływach wcześniejszych języków).

Alternatywy

Z pewnością jest możliwe (i dość proste) stworzenie języka programowania, który ma tylko jeden typ liczb naturalnych nat. Prawie wszystkie języki programowania używane w badaniach akademickich (np. PCF, System F) mają ten jeden typ liczbowy, który, jak się domyślacie, jest bardziej eleganckim rozwiązaniem. Ale projektowanie języka w praktyce nie polega wyłącznie na elegancji; musimy również wziąć pod uwagę wydajność (zakres, w jakim brana jest pod uwagę wydajność, zależy od zamierzonego zastosowania języka). Wydajność obejmuje zarówno czas, jak i przestrzeń.

Ograniczenia przestrzeni

Pozwalając programiście wybrać z góry liczbę bajtów, można zaoszczędzić miejsce w programach o ograniczonej pamięci. Jeśli wszystkie liczby będą mniejsze niż 256, możesz użyć 8 razy więcej bytes niż longs lub użyć zapisanej pamięci dla bardziej złożonych obiektów. Standardowy programista aplikacji Java nie musi się martwić tymi ograniczeniami, ale pojawiają się.

Wydajność

Nawet jeśli zignorujemy miejsce, nadal jesteśmy ograniczeni przez procesor, który ma tylko instrukcje działające na określonej liczbie bajtów (8 bajtów w architekturze 64-bitowej). Oznacza to, że nawet podanie pojedynczego 8-bajtowego longtypu znacznie uprościłoby implementację języka niż posiadanie nieograniczonego typu liczby naturalnej, dzięki możliwości odwzorowania operacji arytmetycznych bezpośrednio na pojedyncze podstawowe instrukcje procesora. Jeśli zezwolisz programiście na użycie dowolnie dużych liczb, wówczas pojedyncza operacja arytmetyczna musi zostać odwzorowana na sekwencję złożonych instrukcji maszyny, co spowolniłoby program. To jest punkt (1), który przywołałeś.

Typy zmiennoprzecinkowe

Dotychczasowa dyskusja dotyczyła tylko liczb całkowitych. Typy zmiennoprzecinkowe to złożona bestia o niezwykle subtelnej semantyce i przypadkowych przypadkach. Tak więc, choć możemy łatwo zastąpić int, long, short, i byteza pomocą jednego nattypu, nie jest jasne, jaki rodzaj liczb zmiennoprzecinkowych nawet jest . Nie są to oczywiście liczby rzeczywiste, ponieważ liczby rzeczywiste nie mogą istnieć w języku programowania. Nie są to również liczby racjonalne (choć w razie potrzeby można łatwo utworzyć racjonalny typ). Zasadniczo IEEE zdecydowało się na sposób przybliżenia liczb rzeczywistych i od tego czasu wszystkie języki (i programiści) utknęli z nimi.

Wreszcie:

Być może programista nie chciałby, aby ktoś mógł użyć liczby większej niż określony rozmiar, co pozwala mu to ograniczyć.

To nie jest prawidłowy powód. Po pierwsze, nie mogę wymyślić żadnych sytuacji, w których typy mogłyby naturalnie kodować granice liczbowe, nie wspominając już o astronomicznie niskich szansach, że granice, które programista chce egzekwować, odpowiadają dokładnie rozmiarom dowolnego z pierwotnych typów.

ogrodnik
źródło
2
prawdziwym kluczem do tego, że mamy zmiennoprzecinkowe, jest to, że mamy dla nich dedykowany sprzęt
jk.
także kodowanie granic numerycznych w typie absolutnie dzieje się w językach zależnych, aw mniejszym stopniu w innych językach, np. jako wyliczenia
jk.
3
Wyliczenia nie są równoważne liczbom całkowitym. Wyliczenia są tylko sposobem użycia typów sum. Fakt, że niektóre języki w przejrzysty sposób kodują wyliczenia jako liczby całkowite, jest wadą językową, a nie funkcją, którą można wykorzystać.
ogrodnik
1
Nie znam Adi. Czy mogę ograniczyć liczby całkowite do dowolnego typu, np. type my_type = int (7, 2343)?
ogrodnik
1
Tak. Składnia wyglądałaby następująco: typ my_type to zakres 7..2343
Devsman 27.09.16
9

Powód jest bardzo prosty: wydajność . Na wiele sposobów.

  1. Rodzime typy danych: Im bardziej typy danych języka odpowiadają bazowym typom danych sprzętu, tym bardziej efektywny jest język. (Nie w tym sensie, że twoje programy będą koniecznie wydajne, ale w tym sensie, że jeśli naprawdę wiesz, co robisz, możesz napisać kod, który będzie działał tak wydajnie, jak sprzęt może go uruchomić.) Oferowane typy danych przez Java odpowiada bajtom, słowom, podwójnym słowom i poczwórnym słowom najpopularniejszego sprzętu. To najbardziej efektywny sposób.

  2. Nieuzasadnione koszty ogólne w systemach 32-bitowych: gdyby podjęto decyzję o odwzorowaniu wszystkiego na stały rozmiar 64-bitowy, nałożyłoby to ogromną karę na architektury 32-bitowe, które potrzebują znacznie więcej cykli zegara, aby wykonać 64- operacja bitowa niż operacja 32-bitowa.

  3. Marnotrawstwo pamięci: istnieje wiele sprzętu, który nie jest zbyt wybredny w zakresie wyrównywania pamięci (przykłady to architektury Intel x86 i x64), więc tablica 100 bajtów na tym sprzęcie może zajmować tylko 100 bajtów pamięci. Jeśli jednak nie masz już bajtu i zamiast tego musisz użyć długiej, ta sama tablica zajmie pamięć o rząd wielkości. A tablice bajtów są bardzo powszechne.

  4. Obliczanie wielkości liczb: Twoje pojęcie dynamicznego określania wielkości liczby całkowitej w zależności od tego, jak duża była przekazywana liczba, jest zbyt uproszczone; nie ma jednego punktu „przekazania” liczby; obliczenie, jak duża musi być liczba, musi zostać wykonane w czasie wykonywania, dla każdej pojedynczej operacji, która może wymagać wyniku większego rozmiaru: za każdym razem, gdy liczba jest zwiększana, za każdym razem, gdy dodajesz dwie liczby, za każdym razem mnożąc dwie liczby itp.

  5. Operacje na liczbach o różnych rozmiarach: Następnie posiadanie w pamięci liczb o potencjalnie różnych rozmiarach skomplikowałoby wszystkie operacje: Nawet w celu zwykłego porównania dwóch liczb środowisko wykonawcze musiałoby najpierw sprawdzić, czy obie liczby do porównania są takie same rozmiar, a jeśli nie, zmień rozmiar mniejszego, aby dopasować go do większego.

  6. Operacje wymagające określonych rozmiarów operandów: Niektóre operacje bitowe zależą od liczby całkowitej mającej określony rozmiar. Ponieważ nie określono wcześniej określonego rozmiaru, operacje te musiałyby zostać emulowane.

  7. Narzut polimorfizmu: zmiana rozmiaru liczby w czasie wykonywania oznacza w zasadzie, że musi być polimorficzna. To z kolei oznacza, że ​​nie może być prymitywem o stałym rozmiarze przydzielonym na stosie, musi to być obiekt przydzielony na stercie. To jest okropnie nieefektywne. (Ponownie przeczytaj nr 1 powyżej.)

Mike Nakis
źródło
6

Aby uniknąć powtarzania punktów, które zostały omówione w innych odpowiedziach, spróbuję nakreślić wiele perspektyw.

Z perspektywy projektowania języka

  • Z pewnością możliwe jest zaprojektowanie i wdrożenie języka programowania i jego środowiska wykonawczego, które automatycznie dostosują wyniki operacji na liczbach całkowitych, które nie mieszczą się w szerokości maszyny.
  • Projektant języka decyduje, czy takie liczby całkowite o dynamicznej szerokości będą domyślnym typem liczb całkowitych dla tego języka.
  • Projektant języka musi jednak wziąć pod uwagę następujące wady:
    • Procesor będzie musiał wykonać więcej kodu, co zajmuje więcej czasu. Można jednak zoptymalizować pod kątem najczęstszego przypadku, w którym liczba całkowita mieści się w jednym słowie maszynowym. Zobacz oznaczoną reprezentację wskaźnika .
    • Rozmiar tej liczby całkowitej staje się dynamiczny.
    • Odczytywanie liczby całkowitej szerokości dynamicznej z pamięci może wymagać więcej niż jednego wyłączenia.
    • Struktury (obiekty) i tablice, które zawierają liczby całkowite o dynamicznej szerokości w swoich polach / elementach, będą miały również dynamiczny całkowity (zajęty) rozmiar.

Przyczyny historyczne

Jest to już omówione w artykule Wikipedii na temat historii Javy, a także krótko omówione w odpowiedzi Marco13 .

Chciałbym zauważyć, że:

  • Projektanci języków muszą pogodzić estetykę z pragmatycznym nastawieniem. Estetyczny sposób myślenia chce zaprojektować język, który nie jest podatny na znane problemy, takie jak przepełnienie liczb całkowitych. Pragmatyczny sposób myślenia przypomina projektantowi, że język programowania musi być wystarczająco dobry, aby wdrażać przydatne aplikacje i współpracować z innymi częściami oprogramowania, które są implementowane w różnych językach.
  • Języki programowania, które zamierzają przejąć udział w rynku ze starszych języków programowania, mogą być bardziej pragmatyczne. Jedną z możliwych konsekwencji jest to, że chętniej włączają lub pożyczają istniejące konstrukcje i style programowania z tych starszych języków.

Przyczyny wydajności

Kiedy wydajność ma znaczenie?

  • Jeśli zamierzasz zareklamować język programowania jako odpowiedni do tworzenia aplikacji na dużą skalę.
  • Kiedy musisz pracować nad milionami i miliardami małych przedmiotów, w których liczy się każda wydajność.
  • Kiedy musisz konkurować z innym językiem programowania, Twój język musi działać przyzwoicie - nie musi być najlepszy, ale z pewnością pomaga pozostać blisko najlepszej wydajności.

Wydajność przechowywania (w pamięci lub na dysku)

  • Pamięć komputerowa była kiedyś rzadkim zasobem. W tamtych czasach rozmiar danych aplikacji, które mogły być przetwarzane przez komputer, był ograniczony ilością pamięci komputera, chociaż można to prawdopodobnie obejść za pomocą sprytnego programowania (którego wdrożenie byłoby droższe).

Wydajność wykonania (w procesorze lub między procesorem a pamięcią)

  • Omówiono to już w odpowiedzi ogrodnika .
  • Jeśli program musi przetwarzać bardzo duże tablice małych liczb przechowywanych kolejno, wydajność reprezentacji w pamięci ma bezpośredni wpływ na wydajność jej wykonywania, ponieważ duża ilość danych powoduje, że przepustowość między procesorem a pamięcią staje się wąskim gardłem. W takim przypadku upakowanie danych w bardziej gęsty sposób oznacza, że ​​pobranie jednej linii pamięci podręcznej może pobrać więcej fragmentów danych.
  • Jednak to rozumowanie nie ma zastosowania, jeśli dane nie są przechowywane lub przetwarzane kolejno.

Potrzeba języków programowania zapewniających abstrakcję dla małych liczb całkowitych, nawet jeśli jest ograniczona do określonych kontekstów

  • Potrzeby te często pojawiają się przy opracowywaniu bibliotek oprogramowania, w tym własnych bibliotek standardowych języka. Poniżej kilka takich przypadków.

Interoperacyjność

  • Często języki programowania wyższego poziomu muszą wchodzić w interakcje z systemem operacyjnym lub oprogramowaniem (bibliotekami) napisanymi w innych językach niższego poziomu. Te języki niższego poziomu często komunikują się za pomocą „struktur” , które są sztywną specyfikacją układu pamięci rekordu składającego się z pól różnych typów.
  • Na przykład język wyższego poziomu może wymagać określenia, że ​​pewna funkcja obca akceptuje chartablicę o rozmiarze 256. (Przykład.)
  • Niektóre abstrakty używane przez systemy operacyjne i systemy plików wymagają użycia strumieni bajtów.
  • Niektóre języki programowania oferują funkcje użytkowe (np. BitConverter) Ułatwiające pakowanie i rozpakowywanie wąskich liczb całkowitych do strumieni bitów i strumieni bajtów.
  • W takich przypadkach węższe typy liczb całkowitych nie muszą być typem pierwotnym wbudowanym w język. Zamiast tego można je podać jako typ biblioteki.

Obsługa ciągów

  • Istnieją aplikacje, których głównym celem projektowania jest manipulowanie ciągami. Dlatego wydajność obsługi ciągów jest ważna dla tego typu aplikacji.

Obsługa formatu pliku

  • Wiele formatów plików zostało zaprojektowanych w sposób podobny do C. Jako takie powszechne było stosowanie pól o wąskiej szerokości.

Celowość, jakość oprogramowania i odpowiedzialność programisty

  • W przypadku wielu rodzajów aplikacji automatyczne poszerzanie liczb całkowitych nie jest w rzeczywistości pożądaną funkcją. Ani nasycenie, ani zawijanie (moduł).
  • Wiele rodzajów aplikacji skorzysta z wyraźnego określenia przez programistę największych dozwolonych wartości w różnych krytycznych punktach oprogramowania, na przykład na poziomie API.

Rozważ następujący scenariusz.

  • Programowy interfejs API akceptuje żądanie JSON. Żądanie zawiera tablicę żądań potomnych. Całe żądanie JSON można skompresować za pomocą algorytmu Deflate.
  • Złośliwy użytkownik tworzy żądanie JSON zawierające miliard żądań potomnych. Wszystkie żądania podrzędne są identyczne; złośliwy użytkownik zamierza, aby system spalił niektóre cykle procesora, wykonując bezużyteczną pracę. Z powodu kompresji te identyczne żądania potomne są kompresowane do bardzo małego całkowitego rozmiaru.
  • Oczywiste jest, że z góry określony limit skompresowanego rozmiaru danych nie jest wystarczający. Zamiast tego interfejs API musi nałożyć z góry określony limit liczby żądań podrzędnych, które mogą się w nim znajdować, i / lub z góry określony limit deflowanego rozmiaru danych.

Często oprogramowanie, które można bezpiecznie skalować o wiele rzędów wielkości, musi być zaprojektowane w tym celu ze zwiększającą się złożonością. Nie przychodzi automatycznie, nawet jeśli problem przepełnienia liczb całkowitych zostanie wyeliminowany. Dzieje się to w pełnym kręgu odpowiadającym perspektywie projektowania języka: często oprogramowanie, które odmawia wykonania pracy, gdy nastąpi niezamierzone przepełnienie liczb całkowitych (przez zgłoszenie błędu lub wyjątku), jest lepsze niż oprogramowanie, które automatycznie wykonuje astronomicznie duże operacje.

Oznacza to perspektywę PO,

Dlaczego osoba musi ustawić, ile bajtów należy użyć dla wartości pierwotnej?

nie jest poprawne. Programiści powinni mieć możliwość, a czasem wymagane, określenie maksymalnej wielkości , jaką może przyjąć wartość całkowita w krytycznych częściach oprogramowania. Jak wskazuje odpowiedź ogrodnika , naturalne ograniczenia narzucone przez prymitywne typy nie są przydatne w tym celu; język musi zapewniać programistom sposoby deklarowania wielkości i egzekwowania takich ograniczeń.

rwong
źródło
2

Wszystko pochodzi od sprzętu.

Bajt to najmniejsza adresowalna jednostka pamięci na większości urządzeń.

Każdy wspomniany typ jest zbudowany z pewnej wielokrotności bajtów.

Bajt ma 8 bitów. Dzięki temu możesz wyrazić 8 booleanów, ale nie możesz wyszukać tylko jednego na raz. Adresujesz 1, adresujesz wszystkie 8.

Kiedyś było to takie proste, ale potem przeszliśmy z 8-bitowej magistrali na 16, 32, a teraz 64-bitową.

Co oznacza, że ​​chociaż wciąż możemy adresować na poziomie bajtów, nie możemy odzyskać ani jednego bajtu z pamięci bez uzyskania sąsiednich bajtów.

W obliczu tego sprzętu projektanci języków postanowili pozwolić nam wybrać typy, które pozwoliły nam wybrać typy pasujące do sprzętu.

Możesz twierdzić, że taki szczegół może i powinien zostać wyodrębniony, zwłaszcza w języku, który ma działać na dowolnym sprzęcie. Miałoby to ukryte problemy z wydajnością, ale możesz mieć rację. Po prostu tak się nie stało.

Java faktycznie próbuje to zrobić. Bajty są automatycznie promowane do Ints. Fakt, który doprowadzi Cię do szału przy pierwszej próbie wykonania jakiejkolwiek poważnej zmiany.

Dlaczego więc nie zadziałało dobrze?

Wielką zaletą Javy jest to, że można było usiąść ze znanym dobrym algorytmem C, wpisać go w Javie i przy drobnych poprawkach zadziałałoby. A C jest bardzo blisko sprzętu.

Utrzymywanie tego i wyodrębnianie rozmiaru z integralnych typów po prostu nie działało razem.

Więc mogliby. Po prostu nie.

Być może programista nie chciałby, aby ktoś mógł użyć liczby większej niż określony rozmiar, co pozwala mu to ograniczyć.

To jest prawidłowe myślenie. Istnieją na to sposoby. Funkcja zacisku dla jednego. Język może posunąć się tak daleko, że ustanowi dowolne granice dla swoich typów. A kiedy te granice są znane w czasie kompilacji, pozwoli to na optymalizację sposobu przechowywania tych liczb.

Java po prostu nie jest tym językiem.

candied_orange
źródło
Język może posunąć się tak daleko, aby wprowadzić dowolne granice w swoich typach ” I rzeczywiście Pascal ma taką formę z podzakresami.
Peter Taylor
1

Prawdopodobnie jednym z ważnych powodów, dla których te typy istnieją w Javie, jest prosty i niepokojąco nietechniczny:

C i C ++ również miały te typy!

Chociaż trudno jest udowodnić, że jest to powód, istnieją co najmniej pewne mocne dowody: Specyfikacja języka dębowego (wersja 0.2) zawiera następujący fragment:

3.1 Typy liczb całkowitych

Liczby całkowite w języku Oak są podobne do liczb w C i C ++, z dwoma wyjątkami: wszystkie typy liczb całkowitych są niezależne od maszyny, a niektóre tradycyjne definicje zostały zmienione, aby odzwierciedlić zmiany w świecie od czasu wprowadzenia C. Cztery typy liczb całkowitych mają szerokość 8, 16, 32 i 64 bitów i są podpisane, chyba że unsignedmodyfikator poprzedzi je .

Pytanie może sprowadzać się do:

Dlaczego krótkie, int i długie zostały wynalezione w C?

Nie jestem pewien, czy odpowiedź na pytanie listowe jest zadowalająca w kontekście zadanego tutaj pytania. Ale w połączeniu z innymi odpowiedziami tutaj może stać się jasne, że posiadanie tych typów może być korzystne (niezależnie od tego, czy ich istnienie w Javie jest jedynie dziedzictwem C / C ++).

Najważniejsze powody, o których mogę myśleć

  • Bajt to najmniejsza adresowalna jednostka pamięci (jak już wspomniano CandiedOrange). A byteto podstawowy element danych, który można odczytać z pliku lub przez sieć. Niektóre powinny istnieć wyraźne przedstawienie tego procesu (i to nie istnieje w większości języków, nawet jeśli czasem przychodzi w przebraniu).

  • Prawdą jest, że w praktyce sensowne byłoby reprezentowanie wszystkich pól i zmiennych lokalnych za pomocą jednego typu i wywoływanie tego typu int. Istnieje pokrewne pytanie na ten temat podczas przepływu stosu: Dlaczego interfejs API Java używa int zamiast krótkiego lub bajtu? . Jak wspomniałem w mojej odpowiedzi, jednym z uzasadnień posiadania mniejszych typów ( bytei short) jest to, że możesz tworzyć tablice tych typów: Java ma reprezentację tablic, która wciąż jest raczej „bliska sprzętowi”. W przeciwieństwie do innych języków (i w przeciwieństwie do tablic obiektów, takich jak Integer[n]tablica), int[n]tablica nie jest zbiorem referencji, w których wartości są rozproszone po całym stosie. Zamiast tego będziew praktyce być kolejnym blokiem n*4bajtów - jednym kawałkiem pamięci o znanym rozmiarze i układzie danych. Gdy masz do wyboru przechowywanie 1000 bajtów w zbiorze obiektów o wartościach całkowitych o dowolnym rozmiarze lub w byte[1000](który zajmuje 1000 bajtów), ten ostatni może rzeczywiście zaoszczędzić trochę pamięci. (Niektóre inne zalety tego mogą być bardziej subtelne i stają się oczywiste tylko w przypadku łączenia Javy z bibliotekami natywnymi)


Odnośnie punktów, o które konkretnie pytałeś:

Czy nie można dynamicznie określić rozmiaru w zależności od tego, jak duża była przekazywana liczba?

Dynamiczne ustawienie rozmiaru danych oznaczałoby, że musiałaby również istnieć możliwość dynamicznej zmiany. Może to potencjalnie powodować problemy z wydajnością?

Prawdopodobnie byłoby możliwe dynamiczne ustawienie wielkości zmiennych, gdyby wziąć pod uwagę zaprojektowanie zupełnie nowego języka programowania od zera. Nie jestem ekspertem w budowie kompilatorów, ale myślę, że trudno byłoby rozsądnie manipulować kolekcjami dynamicznie zmieniających się typów - szczególnie, gdy masz mocno napisany język. Prawdopodobnie sprowadzałoby się to do tego, że wszystkie liczby są przechowywane w „ogólnym, arbitralnym typie danych liczbowych o precyzji precyzyjnej”, co z pewnością miałoby wpływ na wydajność. Oczywiście, nie języki programowania, które są silnie wpisane i / lub zaoferować dowolnie wielkości typów numerycznych, ale nie sądzę, że jest to prawdziwy język programowania ogólnego przeznaczenia, który udał się w ten sposób.


Notatki dodatkowe:

  • Być może zastanawiałeś się nad unsignedmodyfikatorem wymienionym w specyfikacji Oak. W rzeczywistości zawiera także uwagę: unsignednie jest jeszcze zaimplementowany; może nigdy nie będzie”. . I mieli rację.

  • Oprócz zastanawiania się, dlaczego C / C ++ w ogóle ma te różne typy liczb całkowitych, możesz zastanawiać się, dlaczego tak je pomieszali, że nigdy nie wiesz, ile bitów intma. Uzasadnienia tego są zwykle związane z wydajnością i można je sprawdzić gdzie indziej.

Marco13
źródło
0

To z pewnością pokazuje, że jeszcze nie uczysz o wydajności i architekturze.

  • Po pierwsze, nie każdy procesor może obsługiwać duże typy, dlatego musisz znać ograniczenia i pracować z tym.
  • Po drugie, mniejsze typy oznaczają większą wydajność podczas wykonywania operacji.
  • Również rozmiar ma znaczenie, jeśli musisz przechowywać dane w pliku lub bazie danych, rozmiar wpłynie zarówno na wydajność, jak i ostateczny rozmiar wszystkich danych, na przykład, powiedzmy, że masz tabelę z 15 kolumnami i otrzymujesz kilka miliony rekordów. Różnica między wybranym małym i niezbędnym rozmiarem dla każdej kolumny lub wybranym tylko największym typem będzie różnicą możliwych Gigabajtów danych i czasu w wykonywaniu operacji.
  • Ma to również zastosowanie w złożonych obliczeniach, w których rozmiar przetwarzanych danych będzie miał duży wpływ, na przykład w grach.

Ignorując znaczenie wielkości danych, zawsze wpływa to na wydajność, musisz zużywać tyle zasobów, ile to konieczne, ale nigdy więcej, zawsze!

Taka jest różnica między programem lub systemem, który robi naprawdę proste rzeczy i jest niesamowicie nieefektywny, wymagający dużej ilości zasobów i powodujący, że korzystanie z tego systemu jest naprawdę kosztowne; lub system, który dużo robi, ale działa szybciej niż inne i jest naprawdę tani w obsłudze.

Nestor Mata Cuthbert
źródło
0

Istnieje kilka dobrych powodów

(1) podczas gdy przechowywanie jednego bajtu zmiennych wierszowych jeden długi jest nieznaczne, przechowywanie milionów w tablicy jest bardzo znaczące.

(2) „natywna” arytmetyka oparta na konkretnych liczbach całkowitych może być znacznie wydajniejsza, a dla niektórych algorytmów na niektórych platformach może być ważna.

ddyer
źródło