2009-09-13 13 views

risposta

0

Nei compilatori Borland e Microsoft, __int64 è probabilmente il più grande che si possa ottenere.

9

Il tipo di dati long long è il più grande dei tipi di dati integrati incorporati nello standard C99 e C++ 0x. Come per tutti gli altri tipi di dati integrati, a long long non viene fornita una dimensione esatta in byte. Invece, è definito come almeno un numero intero a 64 bit. Mentre long long non fa parte dello standard ufficiale C++, è supportato ovunque sui moderni compilatori. Si noti, tuttavia, che molti compilatori per desktop moderni definiscono long e long long come entrambi esattamente 64 bit, mentre molti compilatori per processori incorporati definiscono long come 32 bit e long long come 64 bit (ovviamente con poche eccezioni).

Se è necessaria una maggiore precisione o non è assolutamente possibile utilizzare l'estensione di linguaggio long long, sarà necessario utilizzare una delle librerie C o C++ progettate per funzionare con numeri estremamente grandi o piccoli.

+3

"... come lungo e lungo saranno entrambi 64-bit sulla maggior parte delle moderne CPU desktop." Non vero. Dipende dal compilatore. Nel modello LLP64 (che è usato da VC), 'long' rimane a 32 bit e' long long' è a 64 bit. –

+1

Vedere questo link http://en.wikipedia.org/wiki/LLP64#Specific_data_models per i possibili modelli di memoria a 64 bit. –

+10

FYI, 'long long' non è nello standard C++. È aggiunto a C in C99. Attualmente è un'estensione diffusa supportata dalla maggior parte dei compilatori. –

2

È possibile ottenere facilmente un tipo di dati più grande definendo la propria classe. Puoi ispirarti alla classe BigInteger in Java. È bello ma non è necessariamente un numero intero, anche se si comporta esattamente come uno.

4

Esistono formati interi a 128 bit e in virgola mobile definiti in xmmintrin.h su compilatori che supportano SSE per abilitare l'uso dei registri e delle istruzioni SSE. Naturalmente non fanno parte dello standard C++, ma dal momento che sono supportati da MSVC, GCC e il compilatore C++ Intel, esiste un certo grado di supporto multipiattaforma (almeno OS X, Linux e Windows per le CPU Intel). Altri ISA hanno estensioni SIMD quindi ci sono probabilmente altre estensioni specifiche per piattaforma/compilatore che supportano le istruzioni SIMD a 128 o 256 bit. Il prossimo set di istruzioni AVX di Intel avrà registri a 256 bit, quindi dovremmo vedere un nuovo set di tipi di dati e di elementi intrinseci.

Non si comportano come i tipi di dati incorporati (vale a dire, è necessario utilizzare le funzioni intrinseche anziché gli operatori per manipolarli e funzionano con le operazioni SIMD), ma poiché in realtà vengono mappati a 128 bit registra sull'hardware che meritano di essere menzionati.

Details about Streaming SIMD Extension (SSE)Intrinsics

21

Il più grande tipo intero norma C++ è long.

C ha un long long e C++ 0x sta per aggiungere anche questo e, naturalmente, è possibile implementare il proprio tipo di intero personalizzato, forse anche una classe BigInt.

Ma tecnicamente parlando, considerando i tipi di interi integrati, long è la vostra risposta.

+1

Tecnicamente, il prossimo standard C++ potrebbe non avere il tipo long long. Non c'è nulla che non possa essere tirato dallo standard nemmeno in questa fase avanzata. Ma +1 per essere un pedante (corretto) :-) – paxdiablo

+3

e hai chiamato * me * un pedante. ;) Ma sì, giusto punto. Al momento, sembra che verrà incluso in C++ 0x, ma chi lo sa. :) – jalf

+8

Ora sappiamo che "long long" è in C++ 11. –

7

È preferibile evitare di preoccuparsi dei nomi primitivi eseguendo il mapping sul tipo più grande (completamente realizzato) dell'architettura di compilazione tramite <cstdint> e i suoi typedef intmax_t e uintmax_t.

Sono rimasto sorpreso che nessun altro l'abbia detto, ma una ricerca superficiale indica che è stata aggiunta in C++ 11, che probabilmente può spiegare la mancanza di menzioni precedenti. (Anche se il suo nuovo primitivo/built-in tipo long longè stato citato!)

Alcuni compilatori possono anche fornire i tipi più grandi, anche se questi possono venire con avvertimenti, per esempio: Why in g++ std::intmax_t is not a __int128_t?

Personalmente, sto usando cstdint come è più facile vedere rapidamente quanti byte minima Sono usando - piuttosto che dover ricordare quanti bit corrisponde a un dato primitivo - e lo standard significa che evita che i miei tipi siano dipendenti dalla piattaforma. Inoltre, per quello che faccio, uint8_t è più veloce e più ordinata di infinita unsigned char s!

modificare: Col senno di poi, ci tengo a precisare: uint8_t non è garantito per essere equivalente a unsigned char. Certo, è sulle mie macchine, e probabilmente lo è anche per te. Ma questa equivalenza non è richiesta dallo Standard; vedi: When is uint8_t ≠ unsigned char? Per questo motivo, ora quando ho bisogno delle abilità speciali definite dallo standard di [[un]signed] char, lo uso solo.

+0

downvoter: C'è un problema reale che puoi dire al resto di noi o ti senti amareggiato per qualcosa che non è collegato? –

3

boost::multiprecision::cpp_int è un tipo di intero di precisione arbitrario. Quindi non esiste "il più grande tipo di dati intero" in C++. Solo un più grande integrato nel tipo integrale, che AFAIK è long in C++ standard.

0

I tipi di dati __int128_t e __uint128_t (unsigned __int128_t) sono lunghi 128 bit, il doppio della dimensione di un long long (che è lungo 64 bit per quelli nuovi in ​​C++). Tuttavia, se si intende utilizzarli, è necessario eseguire un po 'di overloading perché il tipo di dati int128 non è troppo supportato (almeno in Mingw). Questo è un esempio di come si può utilizzare per mostrare 2^x-1 fino a 2^128-1

#include <iostream> 

char base10_lookup_table[10]={'0','1','2','3','4','5','6','7','8','9'}; 

std::ostream& 
operator<<(std::ostream& dest, __int128 value) 
{ 
    std::ostream::sentry s(dest); 
    if (s) { 
     __uint128_t tmp = value < 0 ? -value : value; 
     char buffer[ 128 ]; 
     char* d = std::end(buffer); 
     do 
     { 
      -- d; 
      *d = base10_lookup_table[ tmp % 10 ]; 
      tmp /= 10; 
     } while (tmp != 0); 
     if (value < 0) { 
      -- d; 
      *d = '-'; 
     } 
     int len = std::end(buffer) - d; 
     if (dest.rdbuf()->sputn(d, len) != len) { 
      dest.setstate(std::ios_base::badbit); 
     } 
    } 
    return dest; 
} 

std::ostream& 
operator<<(std::ostream& dest, unsigned __int128 value) 
{ 
    std::ostream::sentry s(dest); 
    if (s) { 
     __uint128_t tmp = value < 0 ? -value : value; 
     char buffer[ 128 ]; 
     char* d = std::end(buffer); 
     do 
     { 
      -- d; 
      *d = base10_lookup_table[ tmp % 10 ]; 
      tmp /= 10; 
     } while (tmp != 0); 
     if (value < 0) { 
      -- d; 
      *d = '-'; 
     } 
     int len = std::end(buffer) - d; 
     if (dest.rdbuf()->sputn(d, len) != len) { 
      dest.setstate(std::ios_base::badbit); 
     } 
    } 
    return dest; 
} 



int main (void) 
{ 
    __uint128_t big_value = 0;  //unsigned int128 

    for (unsigned char i=0; i!=129; ++i) //I am using an unsigned char because it can hold all the values that will be used 
    { 
     std::cout << "1 less than 2 to the power of " << int(i) << " = \0" << big_value << "\n"; 
     big_value |= (__uint128_t)1 << i; 
    } 

    return 0; //formal way of exiting 
} 

Il problema con il tipo di dati int128 è che non tutti i compilatori potrebbero sostenerlo.

Problemi correlati