An liczba całkowita jest typem całkowitym, który może reprezentować dodatnie i ujemne liczby całkowite, w tym 0 (np. -2, -1, 0, 1, 2). C++ ma 4 podstawowe podstawowe typy całkowite dostępne do użycia:
| Typ | Minimum Rozmiar | Uwaga |
|---|---|---|
| short int | 16 bitów | |
| int | 16 bitów | Zwykle 32 bity w nowoczesnych architekturach |
| long int | 32 bity | |
| długi długi wew | 64 bity |
Kluczowa różnica między różnymi typami liczb całkowitych polega na tym, że mają one różne rozmiary — większe liczby całkowite mogą przechowywać większe liczby.
Przypomnienie
C++ gwarantuje jedynie, że liczby całkowite będą miały określony minimalny rozmiar, a nie, że będą miały określony rozmiar. Zobacz lekcję 4.3 -- Rozmiary obiektów i operator sizeof aby uzyskać informacje na temat określania wielkości każdego typu na komputerze.
Na marginesie…
Technicznie rzecz biorąc, bool i char typy są uważane za typy całkowite (ponieważ typy te przechowują swoje wartości jako wartości całkowite). Na potrzeby następnych kilku lekcji wykluczymy te typy z naszej dyskusji.
Liczby całkowite ze znakiem
Pisząc liczby ujemne w życiu codziennym, używamy znaku ujemnego. Na przykład, -3 oznacza „ujemne 3”. Zwykle też rozpoznajemy +3 jako „dodatnia 3” (chociaż powszechna konwencja nakazuje, aby zazwyczaj pomijać przedrostki plus).
Ten atrybut bycia dodatnim, ujemnym lub zerowym nazywany jest liczbą podpisać.
Domyślnie liczbami całkowitymi w C++ są podpisany, co oznacza, że znak liczby jest przechowywany jako część wartości. Dlatego liczba całkowita ze znakiem może zawierać zarówno liczby dodatnie, jak i ujemne (oraz 0).
W tej lekcji skupimy się na liczbach całkowitych ze znakiem. Liczby całkowite bez znaku (które mogą zawierać tylko liczby nieujemne) omówimy w następnej lekcji.
Definiowanie liczb całkowitych ze znakiem
Oto preferowany sposób definiowania czterech typów liczb całkowitych ze znakiem:
short s; // prefer "short" instead of "short int"
int i;
long l; // prefer "long" instead of "long int"
long long ll; // prefer "long long" instead of "long long int"Chociaż short int, long int lub długi długi wew będzie działać, wolimy krótkie nazwy dla tych typów (które nie używają rozszerzenia int przyrostek). Oprócz częstszego pisania, dodanie pliku int sufiks sprawia, że typ jest trudniejszy do odróżnienia od zmiennych typu int. Może to prowadzić do błędów, jeśli przypadkowo pominiesz krótki lub długi modyfikator.
Typy całkowite mogą również przyjmować opcję opcjonalną podpisany słowo kluczowe, które zgodnie z konwencją jest zwykle umieszczane przed nazwą typu:
signed short ss;
signed int si;
signed long sl;
signed long long sll;Jednak tego słowa kluczowego nie należy używać, ponieważ jest ono zbędne, ponieważ liczby całkowite są domyślnie podpisane.
Najlepsza praktyka
Preferuj typy skrócone, które nie używają int przyrostek lub signed prefiksu.
Zakresy liczb całkowitych ze znakiem
Jak dowiedziałeś się z ostatniej sekcji, zmienna with n bity mogą pomieścić 2n możliwe wartości. Ale jakie konkretne wartości? Nazywamy zbiorem określonych wartości, jakie może przechowywać typ danych zakresem. Zakres zmiennej całkowitej jest określony przez dwa czynniki: jej rozmiar (w bitach) oraz to, czy jest ona ze znakiem, czy nie.
Na przykład 8-bitowa liczba całkowita ze znakiem ma zakres od -128 do 127. Oznacza to, że 8-bitowa liczba całkowita ze znakiem może bezpiecznie przechowywać dowolną wartość całkowitą z zakresu od -128 do 127 (włącznie).
Oto tabela zawierająca zakres liczb całkowitych ze znakiem o różnych rozmiarach:
| Rozmiar/typ | Zakres |
|---|---|
| Podpisany 8-bitowo | -128 do 127 |
| 16-bitowy podpisany | -32 768 do 32 767 |
| Podpisany 32-bitowy | -2 147 483 648 do 2 147 483 647 |
| Podpisany 64-bitowy | -9 223 372 036 854 775 808 do 9 223 372 036 854 775 807 |
W przypadku matematyki n-bitowa zmienna ze znakiem ma zakres -(2n-1) do (2n-1)-1.
Dla osób, które nie mają skłonności do matematyki… skorzystaj z tabeli. :)
Dla zaawansowanych czytelników
Powyższe zakresy zakładają reprezentację binarną „dopełnienia do dwóch”. Ta reprezentacja jest de facto standardem dla nowoczesnych architektur (ponieważ jest łatwiejsza do wdrożenia na sprzęcie) i jest obecnie wymagana przez standard C++ 20. Na lekcji omawiamy uzupełnienie do dwójki O.4 -- Konwersja liczb całkowitych pomiędzy reprezentacją binarną i dziesiętną.
We wcześniejszych standardach reprezentacje wielkości znaku i uzupełnienia były dozwolone ze względów historycznych. Takie reprezentacje dają wartości w zakresie -(2n-1-1) do +(2n-1-1).
Przepełnienie
Co się stanie, jeśli spróbujemy przypisać wartość 140 do 8-bitowej liczby całkowitej ze znakiem? Ta liczba jest poza zakresem, jaki może pomieścić 8-bitowa liczba całkowita ze znakiem. Liczba 140 wymaga 9 bitów do reprezentacji (8 bitów wielkości i 1 bit znaku), ale mamy tylko 8 bitów (7 bitów wielkości i 1 bit znaku) dostępnych w 8-bitowej liczbie całkowitej ze znakiem.
Standard C++20 podaje ogólne stwierdzenie: „Jeśli podczas oceny wyrażenia wynik nie jest zdefiniowany matematycznie lub nie mieści się w zakresie możliwych do przedstawienia wartości dla jego typu, zachowanie jest niezdefiniowane”. Potocznie nazywa się to przepełnieniem.
Dlatego przypisanie wartości 140 do 8-bitowej liczby całkowitej ze znakiem spowoduje niezdefiniowane zachowanie.
Jeśli operacja arytmetyczna (taka jak dodawanie lub mnożenie) próbuje utworzyć wartość spoza zakresu, który można przedstawić, nazywa się to liczbą całkowitą przepełnienie (lub przepełnienie arytmetyczne). W przypadku liczb całkowitych ze znakiem przepełnienie liczb całkowitych spowoduje niezdefiniowane zachowanie.
#include <iostream>
int main()
{
// assume 4 byte integers
int x { 2'147'483'647 }; // the maximum value of a 4-byte signed integer
std::cout << x << '\n';
x = x + 1; // integer overflow, undefined behavior
std::cout << x << '\n';
return 0;
}Na komputerze autora wydrukowano powyższy komunikat:
2147483647 -2147483648
Ponieważ jednak drugie wyjście jest wynikiem niezdefiniowanego zachowania, wartość wyjściowa może się różnić na Twojej maszynie.
Dla zaawansowanych czytelników
Omawiamy, co się dzieje, gdy na lekcji przepełnią się liczby całkowite bez znaku 4.5 -- Liczby całkowite bez znaku i dlaczego ich unikać.
Ogólnie rzecz biorąc, przepełnienie powoduje utratę informacji, co prawie nigdy nie jest pożądane. Jeśli istnieje dowolnego podejrzenie, że obiekt może potrzebować przechowywać wartość spoza jego zakresu, użyj typu o większym zakresie!
Dzielenie na liczbach całkowitych
Podczas dzielenia dwóch liczb całkowitych C++ działa tak, jak można się spodziewać, gdy iloraz jest liczbą całkowitą:
#include <iostream>
int main()
{
std::cout << 20 / 4 << '\n';
return 0;
}Daje to oczekiwany wynik:
5
Ale spójrzmy, co się dzieje, gdy dzielenie liczb całkowitych powoduje wynik ułamkowy:
#include <iostream>
int main()
{
std::cout << 8 / 5 << '\n';
return 0;
}To daje prawdopodobnie nieoczekiwane wynik:
1
Podczas dzielenia dwóch liczb całkowitych (tzw. dzielenie przez liczby całkowite) C++ zawsze daje wynik w postaci liczby całkowitej. Ponieważ liczby całkowite nie mogą przechowywać wartości ułamkowych, każda część ułamkowa jest po prostu pomijana (a nie zaokrąglana!).
Przyglądając się bliżej powyższemu przykładowi, 8 / 5 daje wartość 1,6. Część ułamkowa (0,6) jest odrzucana, a wynik 1 pozostaje. Alternatywnie możemy powiedzieć, że 8 / 5 równa się 1 reszcie 3. Pozostałość jest odrzucana, pozostawiając 1.
Podobnie, -8 / 5 daje wartość -1.
Ostrzeżenie
Bądź ostrożny podczas dzielenia liczb całkowitych, ponieważ stracisz części ułamkowe ilorazu. Jeśli jednak tego chcesz, dzielenie liczb całkowitych jest bezpieczne, ponieważ wyniki są przewidywalne.
Jeśli pożądane są wyniki ułamkowe, na lekcji pokażemy, jak to zrobić. 6.2 — Operatory arytmetyczne.
Czas quizu
Pytanie nr 1
Jaki byłby zakres 5-bitowej liczby całkowitej ze znakiem?
Pytanie nr 2
a) Jaki jest wynik 13 / 5?
b) Jaki jest wynik -13 / 5?

