2009-06-01 6 views
12

Ho una variabile intera, che può ottenere un valore superiore a 4294967295.Quale tipo usare per interi superiori a 2^32 in C++?

Che tipo dovrei usare per questo (molto lungo, o doppio o qualcos'altro)?

+1

potrebbe essere straordinariamente più grande? perché le persone si soffermano su problemi di 64 bit, ma se dici che stai guardando le distanze astronomiche, o gli atomi contano, la risposta passa rapidamente a "raddoppiare", dimenticare gli interi. – jpinto3912

+0

Grande commento! Nel mio caso non diventa più grande di 64 bit, ma è comunque interessante, cosa fare se lo fa? Perché dovrei usare "double" in questo caso? –

risposta

8

Non c'è un modo portatile per farlo in C++, poiché il linguaggio non specifica la dimensione dei tipi interi (tranne sizeof char è 1). È necessario consultare la documentazione del compilatore.

+5

Non proprio vero. Lo standard specifica le magnitudini minime di ogni tipo e quindi implicitamente un conteggio minimo di bit (non di byte) vedi http://stackoverflow.com/questions/271076/che-è-la-differenza-della-an-int-and -a-long-in-c/271132 # 271132 –

+1

Dal C++ 11 ci sono tipi 'long long' e' unsigned long long' che sono garantiti per avere almeno 64 bit di larghezza e il loro rispettivo 'll',' ull letterali Anche nell'intestazione 'cstdint' ci sono gli alias' int64_t', 'int_least64_t',' int_fast64_t', 'uint64_t',' uint_least64_t', 'uint_fast64_t'. –

0

Le doppie sono a virgola mobile. Dovresti usare molto a lungo, probabilmente. Non so quale alias sia il preferito.

13

Utilizzare long long e, se possibile, aggiungere un'asserzione in fase di compilazione che questo tipo sia sufficientemente ampio (smth come).

double è per virgola mobile, non intero.

+9

long long non è un tipo di dati C++ standard –

+5

Secondo ISO/IEC 9899: TC3 - Bozza di commissione - Septermber 7, 2007 - Le principali modifiche apportate alla precedente edizione includono: il lungo int lungo e le funzioni di libreria valore massimo per un oggetto di tipo long long int LLONG_MAX 9223372036854775807 (2^63 - 1) –

+4

Questo è un documento C99, non C++. –

1

se non hai bisogno di numeri negativi, suoni lunghi lunghi senza segno come la maggior parte che puoi ottenere.

2

Io uso

uint64_t 

ma non è standard.

+1

In realtà stdint.h fa parte di C99. Ma molti produttori di compilatori sono riluttanti nel supportare standard "nuovi" anche dopo 10 anni (qualcuno ricorda come appariva l'IT 10 anni fa ?!). – lispmachine

+0

Non so del tuo lavoro, ma per me, contano solo tre produttori di compilatori. Microsoft, Intel e GCC. E tutti e tre sono stati tradizionalmente bravi a "nuovi" standard di conformità. Non tanto SunW C++ o HP o IBM, ma nel mondo Windows/Linux, dovrebbe essere un non-problema. 15 anni fa, ricordo di aver distrutto compilatori e linker per la colazione. In effetti, DEC ha impiegato la parte migliore di due mesi per correggere un bug del linker in modo da poter spedire Pro/ENGINEER per Windows NT Alpha, ai tempi in cui i file eseguibili da 32 MB erano sconosciuti. –

0

Se il compilatore non ha molto tempo si può implementare da soli con una struttura contenente due lunghi, ma sarà necessario essere caurseful con trasportare ecc Si potrebbe, naturalmente, cercare un multiplo aritmetica di precisione come GMP

3

Entrambe le proposte non sono buone perché lungo non è un tipo di dati C++ standard e il doppio è un punto a virgola mobile.

Dal momento che il mio programma deve essere portatile, ho intenzione di #define miei tipi, che si adattano tutti i compilatori che uso (studio visivo e gcc):

#ifdef WIN32 
    #define unsigned_long_long unsigned __int64 
    #define long_long __int64 
#else // gcc. Might not work on other compilers! 
    #define unsigned_long_long unsigned long long 
    #define long_long long long 
#endif 
+1

Nota che questo non è un problema di Windows, è un problema di standard C++ - non è garantito che le piattaforme non Windows supporteranno molto a lungo. –

+0

Secondo MSDN long long equivale a __int64 in VC++ e quindi non è necessario definirlo. – sharptooth

+0

Si noti inoltre che g ++ emetterà molti avvisi se compilati con -pedantic, che penso che la maggior parte dei programmi C++ siano (dovrebbero essere certamente) –

1

Prova TTMath. Tutto quello che devi fare è includere un singolo colpo di testa e poi dichiarare un tipo bignum come ad esempio:

typedef ttmath::UInt<100> BigInt; 

che crea un tipo che può contenere numeri interi senza segno compreso tra 0 e 2^(32 * 100) -1. Quindi utilizzare solo BigInt ovunque si utilizzi int.

Ovviamente è possibile scegliere la dimensione desiderata per il parametro del modello. 100 potrebbe essere eccessivo ;-)

Appena realizzato, la lib funziona solo su x86 e x64, ma è OS multipiattaforma su quei processori.

+0

sono bloccato cercando di usare ttmath e usato quello che hai detto. hai detto che avrebbe dovuto usare BigInt nel posto in cui avrebbe usato Int ma i fatti sono che ottengo questo errore "classe BigInt non ha un membro chiamato ...", perché pensi che stia accadendo? – wxiiir

+0

@wxiir Hai detto nel tuo altro post che stai ricevendo un errore dicendo "BigInt non ha alcun membro chiamato blah' quando la tua variabile è stata chiamata' blah' (che non dovrebbe accadere). Cosa succede prova una semplice dichiarazione come 'ttmath :: UInt <100> blah = 0; blah = blah + 10; '? – HostileFork

3

non uso doppio, perché:

cout.setf(ios::fixed); 
cout << LONG_LONG_MAX << endl; 
cout << double(LONG_LONG_MAX) << endl; 

cout << LONG_LONG_MAX-100 << endl; 
cout << double(LONG_LONG_MAX-100) << endl; 

uscita:

9223372036854775807 
9223372036854775808.000000 
9223372036854775707 
9223372036854775808.000000 
+0

Sì, raddoppierà alcuni dei bit per identificare l'esponente, perdendo di fatto la precisione (rispetto a un tipo intero della stessa dimensione) –

1

un sacco di corrente C/C++ compilatori hanno o intestazione stdint.h o inttypes.h.

int_fast64_t o int64_t possono essere un'opzione (IMHO il più portatile).

7

Suppongo che i numeri si adattino a 64 bit. In caso contrario, è necessario uncome GMP.

In teoria, non esiste un modo semplice e portatile per eseguire calcoli matematici a 64 bit in C++. In pratica, la maggior parte dei compilatori C++ supporta anche le intestazioni C "vecchio stile" e C99 ha una bella intestazione chiamata stdint.h.

Quindi, prima fare:

#include <stdint.h> 

Quindi utilizzare tipi int64_t (firmato) e uint64_t (non firmato).

1

Quanto deve essere portatile il programma? TR1 ha cstdint e stdint.h quindi è probabilmente supportato dai compilatori più aggiornati. Quindi c'è Boost cstdint.hpp che dovresti essere in grado di usare se cstdint non è supportato.

0

Solo per curiosità - Non penso sarebbe troppo difficile codificarlo da soli se lo si desidera. Voglio dire, tutti questi tipi di dati hanno strutture predefinite, ovviamente, ma potresti, ad esempio, utilizzare la struttura double che utilizza esponenti e fare qualcosa del genere:

per contenere un numero MOLTO grande, oltre la scala di un doppio, creare un oggetto che ha due parti ad esso - il numero e la potenza a dieci,

modo, se si voleva conservare qualcosa come

1,123x 10^(100000000000000000000000000000000000), che isn' t supportato da un double, potresti avere la 1.123 ... parte memorizzata in un double, e quindi la potenza di dieci come double double/int/float (qualunque cosa sia), e poi prenderla da lì. Naturalmente, questo potrebbe non essere il modo migliore e probabilmente dovresti codificare molte funzionalità per la divisione, la sottrazione, ecc., Ma sarà sicuramente portatile, dato che useresti i normali tipi di dati definiti. La fruibilità di questo dipenderà da ciò che stai cercando di raggiungere e dal fatto che tu pensi di usarlo al di là di un singolo progetto, ma penso che sia un modo affidabile di farlo se quei numeri sono un requisito assoluto