2012-03-30 13 views
5

Vorrei implementare una classe BigInt che sia in grado di gestire numeri veramente grandi. Voglio solo aggiungere e moltiplicare i numeri, tuttavia la classe dovrebbe anche gestire i numeri negativi.Quale struttura dati dovrei usare per la classe BigInt

Volevo rappresentare il numero come una stringa, ma c'è un grande sovraccarico con la conversione della stringa in int e ritorno per l'aggiunta. Voglio implementare l'aggiunta come al liceo, aggiungere l'ordine corrispondente e se il risultato è maggiore di 10, aggiungere il riporto al prossimo ordine.

Quindi ho pensato che sarebbe stato meglio gestirlo come un array di unsigned long long int e mantenere il segno separato da bool. Con questo ho paura della dimensione dell'int, come standard C++ per quanto ne so garantisce solo che int < float < doppio. Correggimi se sbaglio. Quindi, quando raggiungo un certo numero, devo spostarmi in array in avanti e iniziare ad aggiungere il numero alla successiva posizione dell'array.

Esiste una struttura dati appropriata o migliore per questo?

+0

Suona come un'implementazione ragionevole per me. Ma se usi ULONG, ogni elemento dell'array può contenere un valore compreso tra 0 e 2^32-1 anziché tra 0 e 10. Ciò dovrebbe far risparmiare qualche byte. :-) –

+1

Lo standard garantisce solo 'float <= double' (notare il segno di uguale) – ipc

+0

Sì, è esattamente quello che intendevo. Ma 2^32 - 1 è uguale su Linux e su Solaris? Rispettivamente è la dimensione garantita ovunque? Il mio punto è che, ad esempio, ottengo MyBigIntClass number = "234567434256547"; e comincio a convertire questo numero di stringa nella mia rappresentazione interna nella classe che viene usata per lungo int (forse :-)), e dopo che il numero raggiunge 2^32 mi sposto in un'altra posizione nell'array. È corretto? – user1086004

risposta

5

Quindi, si desidera un array dinamico di numeri interi di una dimensione ben nota?

Suoni come vector<uint32_t> dovrebbero funzionare per voi.

+0

purtroppo STL non è permesso – user1086004

+2

compiti a casa? inserito? In ogni caso, avrai bisogno di qualcosa come 'vector'. Fortunatamente, è un semplice esercizio ricreare un "array dinamico" di base." – Joni

2

Come hai già scoperto, dovrai utilizzare tipi specifici nella tua piattaforma (o nella lingua se hai C++ 11) che hanno una dimensione fissa. Un'implementazione comune di un grande numero userebbe interi a 32 bit e assicurerebbe che siano impostati solo i 16 bit inferiori. Ciò consente di operare sulle cifre (dove cifra sarebbe [0..2^16)) e quindi normalizzare il risultato applicando i riporti.

+0

Per addizione/sottostringa, carry può essere fatto sulla strada e non hai bisogno di due passaggi.Per la moltiplicazione, dipende dall'algoritmo, ma se stai usando, ad esempio, metodi FFT in virgola mobile, non hai bisogno porta anche (ma è meglio usare "cifre" a 16 bit poiché accumulerai errori di arrotondamento durante la FFT.) –

2

Su una moderna piattaforma x86 a 64 bit, l'approccio migliore è probabilmente quello di archiviare il bigint come una matrice allocata dinamicamente di numeri interi a 32 bit senza segno, in modo che la vostra aritmetica possa adattarsi a 64 bit. Puoi gestire il tuo segno separatamente, come variabile membro della classe, oppure puoi usare l'aritmetica del complemento a 2 (che è in genere il modo in cui sono rappresentati gli signed int).

Il file di tipo C <stdint.h> standard definisce uint32_t e uint64_t, quindi è possibile evitare i tipi di integer dipendenti dalla piattaforma. Oppure (se la tua piattaforma non fornisce questi), puoi improvvisare e definire questo tipo di cose da te - preferibilmente in un file "platform_dependent.h" separato ...

+0

Il complemento a 2 s non è facile da fare per i bint di lunghezza dinamica (e non compra molto), ma Sono d'accordo con il resto – Sopel

Problemi correlati