Jaki zakres wartości może przechowywać typy całkowite w C ++

86

Czy może unsigned long intprzechowywać dziesięciocyfrowy numer (1 000 000 000 - 9 999 999 999) na komputerze 32-bitowym?

Dodatkowo, jakie są zakresy unsigned long int, long int, unsigned int, short int, short unsigned int, i int?

yihangho
źródło

Odpowiedzi:

139

Te minimalne zakresy mogą liczyć na to:

  • short inti int: -32 767 do 32767
  • unsigned short inti unsigned int: od 0 do 65 535
  • long int: Od -2 147 483 647 do 2 147 483 647
  • unsigned long int: Od 0 do 4 294 967 295

Oznacza to, że nie, long int nie można polegać na przechowywaniu jakiejkolwiek 10-cyfrowej liczby. Jednak większy typ long long intzostał wprowadzony do C w C99 i C ++ w C ++ 11 (ten typ jest również często obsługiwany jako rozszerzenie przez kompilatory zbudowane dla starszych standardów, które go nie zawierały). Minimalny zakres dla tego typu, jeśli Twój kompilator go obsługuje, to:

  • long long int: Od -9 223 372 036 854 775 807 do 9 223 372 036 854 775 807
  • unsigned long long int: Od 0 do 18 446 744 073 709 551 615

Więc ten typ będzie wystarczająco duży (ponownie, jeśli masz go dostępny).


Uwaga dla tych, którzy uważają, że popełniłem błąd przy tych dolnych granicach - nie zrobiłem. Wymagania C dotyczące zakresów są napisane w celu umożliwienia reprezentacji liczb całkowitych z uzupełnieniem lub znakiem wielkości znaku, gdzie najniższa możliwa do przedstawienia wartość i najwyższa możliwa do przedstawienia wartość różnią się tylko znakiem. Dozwolona jest również reprezentacja uzupełnienia do dwóch, gdzie wartość z bitem znaku 1 i wszystkimi bitami wartości 0 jest reprezentacją pułapki, a nie wartością prawną. Innymi słowy, nieint jest wymagane, aby móc przedstawić wartość -32,768.

kawiarnia
źródło
Tytuł pierwotnie mówił też „C / C ++”.
kawiarnia
dlaczego długi długi int dodatni zakres == ujemny zakres
mohamed abdallah
1
@mohamedabdallah: Zobacz ostatni akapit odpowiedzi: standardowe zakresy C pozwalają na reprezentacje wartości dopełnienia lub wielkości znaku.
kawiarnia
Aha… zdałem sobie sprawę, że intto oznacza long int.
mazend
32

Rozmiar typów liczbowych nie jest zdefiniowany w standardzie C ++, chociaż minimalne rozmiary są. Sposobem na określenie ich rozmiaru na Twojej platformie jest użycie limitów liczbowych

Na przykład maksymalną wartość int można znaleźć przez:

std::numeric_limits<int>::max();

Komputery nie działają na podstawie 10, co oznacza, że ​​maksymalna wartość będzie miała postać 2 n -1 ze względu na to, jak liczby reprezentują się w pamięci. Weźmy na przykład osiem bitów (1 bajt)

  0100 1000

Najbardziej na prawo bit (liczba) ustawiony na 1 reprezentuje 2 0 , następny bit 2 1 , następnie 2 2 i tak dalej, aż dojdziemy do skrajnego lewego bitu, który jeśli liczba jest bez znaku oznacza 2 7 .

Zatem liczba reprezentuje 2 6 + 2 3 = 64 + 8 = 72, ponieważ 4 bit od prawej strony i 7 bit od prawej strony są ustawione.

Jeśli ustawimy wszystkie wartości na 1:

11111111

Liczba ta wynosi teraz (zakładając bez znaku )
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255 = 2 8 - 1
I jak widać, jest to największa możliwa wartość, którą można przedstawić za pomocą 8 bitów.

Na moim komputerze wartości int i long są takie same, każdy z nich może pomieścić od -2 31 do 2 31 - 1. Z mojego doświadczenia wynika, że ​​najczęstszy rozmiar na nowoczesnych komputerach 32-bitowych.

Yacoby
źródło
Minimalne rozmiary dla typu liczb całkowitych są określane przez odpowiednie normy (chociaż dokładne rozmiary nie są wymagane).
kawiarnia
13

Aby poznać ograniczenia w swoim systemie:

#include <iostream>
#include <limits>
int main(int, char **) {
  std::cout
    << static_cast< int >(std::numeric_limits< char >::max()) << "\n"
    << static_cast< int >(std::numeric_limits< unsigned char >::max()) << "\n"
    << std::numeric_limits< short >::max() << "\n"
    << std::numeric_limits< unsigned short >::max() << "\n"
    << std::numeric_limits< int >::max() << "\n"
    << std::numeric_limits< unsigned int >::max() << "\n"
    << std::numeric_limits< long >::max() << "\n"
    << std::numeric_limits< unsigned long >::max() << "\n"
    << std::numeric_limits< long long >::max() << "\n"
    << std::numeric_limits< unsigned long long >::max() << "\n";
}

Zauważ, że long longjest to legalne tylko w C99 i C ++ 11.

Hal Canary
źródło
9

Inni ludzie będą tutaj umieszczać linki do data_sizes i precyzyjności itp.
Powiem ci, jak samemu to rozgryźć .
Napisz małą aplikację, która wykona następujące czynności.

unsigned int ui;
std::cout <<  sizeof(ui));

to (w zależności od kompilatora i architektury) wypisze 2, 4 lub 8, mówiąc o długości 2 bajtów, 4 bajtów itp.

Załóżmy, że to 4.

Teraz chcesz, aby maksymalna wartość, jaką mogą przechowywać 4 bajty, to maksymalna wartość dla jednego bajtu (szesnastkowo) 0xFF. Maksymalna wartość czterech bajtów to 0x, po której następuje 8 f (jedna para f na każdy bajt, 0x mówi kompilatorowi, że następujący ciąg jest liczbą szesnastkową). Teraz zmień program, aby przypisać tę wartość i wydrukuj wynik

unsigned int ui = 0xFFFFFFFF;
std::cout <<  ui;

Jest to maksymalna wartość, jaką może posiadać bez znaku int, pokazana w reprezentacji o podstawie 10.

Teraz zrób to dla długich, szortów i innych wartości INTEGER, które Cię interesują.

Uwaga: to podejście nie będzie działać dla liczb zmiennoprzecinkowych (tj. Podwójnych lub zmiennoprzecinkowych).

Mam nadzieję że to pomoże

Binary Worrier
źródło
1
Jeśli spróbujesz tego z intami ze znakiem, otrzymasz liczby ujemne. Przeczytaj „komplement dla dwóch osób” (link podany), łatwo jest uzyskać pełny zakres (dodatni i ujemny) również dla nich. en.wikipedia.org/wiki/Twos_Compliment
Binary Worrier
8

W C ++ teraz int i inne dane są przechowywane przy użyciu metody komplementów 2. Oznacza to, że zakres wynosi:

-2147483648 to 2147483647

lub od -2 ^ 31 do 2 ^ 31-1

1 bit jest zarezerwowany dla 0, więc wartość dodatnia jest o jeden mniejsza niż 2 ^ (31)

Shah Rukh Qasim
źródło
4

Możesz użyć funkcji numeric_limits<data_type>::min()i numeric_limits<data_type>::max()obecnych w limitspliku nagłówkowym i znaleźć ograniczenia każdego typu danych.

#include <iostream>
#include <limits>
using namespace std;
int main()
{
    cout<<"Limits of Data types:\n";    
    cout<<"char\t\t\t: "<<static_cast<int>(numeric_limits<char>::min())<<" to "<<static_cast<int>(numeric_limits<char>::max())<<endl;
    cout<<"unsigned char\t\t: "<<static_cast<int>(numeric_limits<unsigned char>::min())<<" to "<<static_cast<int>(numeric_limits<unsigned char>::max())<<endl;
    cout<<"short\t\t\t: "<<numeric_limits<short>::min()<<" to "<<numeric_limits<short>::max()<<endl;
    cout<<"unsigned short\t\t: "<<numeric_limits<unsigned short>::min()<<" to "<<numeric_limits<unsigned short>::max()<<endl;
    cout<<"int\t\t\t: "<<numeric_limits<int>::min()<<" to "<<numeric_limits<int>::max()<<endl;
    cout<<"unsigned int\t\t: "<<numeric_limits<unsigned int>::min()<<" to "<<numeric_limits<unsigned int>::max()<<endl;
    cout<<"long\t\t\t: "<<numeric_limits<long>::min()<<" to "<<numeric_limits<long>::max()<<endl;
    cout<<"unsigned long\t\t: "<<numeric_limits<unsigned long>::min()<<" to "<<numeric_limits<unsigned long>::max()<<endl;
    cout<<"long long\t\t: "<<numeric_limits<long long>::min()<<" to "<<numeric_limits<long long>::max()<<endl;
    cout<<"unsiged long long\t: "<<numeric_limits<unsigned long long>::min()<<" to "<<numeric_limits<unsigned long long>::max()<<endl;
    cout<<"float\t\t\t: "<<numeric_limits<float>::min()<<" to "<<numeric_limits<float>::max()<<endl;
    cout<<"double\t\t\t: "<<numeric_limits<double>::min()<<" to "<<numeric_limits<double>::max()<<endl;
    cout<<"long double\t\t: "<<numeric_limits<long double>::min()<<" to "<<numeric_limits<long double>::max()<<endl;
}

Wynik będzie następujący: Limity typów danych:

  • char: -128 do 127
  • unsigned char: od 0 do 255
  • krótki: -32768 do 32767
  • unsigned short: od 0 do 65535
  • int: -2147483648 do 2147483647
  • unsigned int: od 0 do 4294967295
  • długi: od -2147483648 do 2147483647
  • unsigned long: od 0 do 4294967295
  • długi długi: -9223372036854775808 do 9223372036854775807
  • unsigned long long: od 0 do 18446744073709551615
  • pływak: od 1.17549e-038 do 3.40282e + 038
  • podwójna: 2,22507e-308 do 1,79769e + 308
  • długie podwójne: 3,3621e-4932 do 1,18973e + 4932
insearchofcode
źródło
2

Dla typu danych bez znaku nie ma bitu znaku, a wszystkie bity są danymi; podczas gdy dla podpisanego typu danych MSB jest oznaczony jako bit znaku, a pozostałe bity są dla danych.

Aby znaleźć zakres, wykonaj następujące czynności:

Krok: 1 -> Znajdź liczbę bajtów dla podanego typu danych.

Krok: 2 -> Zastosuj następujące obliczenia.

      Let n = no of bits in data type  

      For signed data type ::
            Lower Range = -(2^(n-1)) 
            Upper Range = (2^(n-1)) - 1)  

      For unsigned data type ::
            Lower Range = 0 
            Upper Range = (2^(n)) - 1 

Np

Dla rozmiaru int bez znaku = 4 bajty (32 bity) -> Zakres [0, (2 ^ (32)) - 1]

Dla rozmiaru int ze znakiem = 4 bajty (32 bity) -> Zakres [- (2 ^ (32-1)), (2 ^ (32-1)) - 1]

Ashish
źródło
1

Może unsigned long int przechowywać dziesięciocyfrową liczbę (1 000 000 000 - 9 999 999 999) na komputerze 32-bitowym.

Nie

Justin
źródło
0

Powinieneś przyjrzeć się specjalizacjom szablonu numeric_limits <> dla danego typu. Jest w nagłówku.

PaulJWilliams
źródło