Quanto pessimo sarebbe questo algoritmo che converte una stringa in un numero a precisione multipla?

1

Ho sviluppato una libreria C ++ per calcoli multipli di precisione (numeri interi / punto fisso), assumo numeri positivi.

La classe è qualcosa di simile a:

class Integer {
 public:
   //constructor
   //destructor
   //set
   //overload operators
 private;
  uint32_t *mem;
  int n_bits_stored;
};

Specificamente il //overload operatos ha operatori binari come

Integer Integer::operator+(const Integer& rhs);
Integer Integer::operator-(const Integer& rhs);
Integer Integer::operator*(const Integer& rhs);
Integer Integer::operator/(const Integer& rhs);
Integer Integer::operator%(const Integer& rhs);

ma anche

Integer Integer::operator<<(const int& l);
Integer Integer::operator>>(const int& l);
Integer& Integer::operator<<=(const int& l);
Integer& Integer::operator>>=(const int& l);

con il significato ovvio.

L'idea è di estendere i tipi interi C ++ di base, a parte il fatto che puoi cambiare la larghezza di banda in tempo reale.

Ad ogni modo ... Mi piacerebbe sovraccaricare l'operatore = , che convertirà un oggetto string in un oggetto Integer , qualcosa come

Integer x = "0xFE3425452783DFEABC34532FCAA"

(puoi supporre che i numeri esadecimali siano passati come stringa, quindi posso omettere il prefisso 0x )

Ecco l'approccio che pensavo di poter usare

  • Input: una stringa str che memorizza le cifre esadecimali

  • Output: un Integer oggetto x

    1. Crea una mappa Map m oggetto in cui la chiave appartiene al set {'0','1',...,'E','F'} e i valori sono nel set {0,1,...,E,F} (i primi sono caratteri, i secondi sono numeri interi).
    2. Per ogni elemento nella mappa, memorizza il numero intero equivalente
    3. Init x = 0 (presumiamo anche che sia già dimensionato correttamente, eventualmente se la dimensione non è sufficiente quindi posso semplicemente tritare la stringa equivalente).
    4. Per i = 0 ... str_digits.len-1 (la scansione dovrebbe essere dalla cifra più significativa alla cifra meno significativa).

      4.1. %codice%; // Left shifiting

      4.2. %codice%; // Lancio implicito eseguito

    5. return x = x << 4

So che mi mancano alcuni dettagli ma, si può presumere che il casting da tipi interi sia implementato, come costruttori, il sovraccarico di ogni tipo di operatori è implementato, eccetto per quello specifico che voglio implementare. Ecco le mie domande:

  1. Il mio algoritmo è corretto?
  2. Supponendo che sia corretto è in particolare la parte di memorizzazione delle cifre implementata utilizzando la struttura dei dati della mappa efficiente? Quello che mi preoccupa un po 'è il costo computazionale del recupero di una cifra, perché nel caso in cui la base sia alta questo approccio potrebbe non essere efficiente, giusto? Cosa consiglieresti diversamente?
posta user8469759 06.02.2017 - 12:13
fonte

3 risposte

4

Is my algorithm correct

Se ignoro alcuni piccoli inconvenienti come scrivere {0,1,...,14,15} anziché {0,1,...,E,F} , sembra corretto a prima vista. Ma sinceramente, implementalo e usa un debugger, il codice probabilmente non sarà molto più lungo del tuo testo precedente.

is specifically the digit storing part [..] efficient?

Se intendi per "Recupero di una cifra" l'operazione m[str[i]] , utilizzando una hashmap questa operazione diventa O (1), quindi non è il collo di bottiglia. Ma l'operazione 4.1 avrà probabilmente un tempo di esecuzione proporzionale alla lunghezza di x che è proporzionale a str_digits.len , e mettendo questo in un ciclo con str_digits.len iterazioni si ottiene un'operazione di O (N²).

È efficiente? Non efficiente come potrebbe essere, ovviamente. Ma dovresti chiederti "è abbastanza efficiente per il mio scopo", e questo è qualcosa che puoi scoprire solo tramite la creazione di profili.

    
risposta data 06.02.2017 - 14:47
fonte
2

La mappa non è particolarmente efficiente, rispetto alla semplice aritmetica per convertire un carattere che rappresenta una cifra esadecimale al suo equivalente numerico. Controlla il codice ASCII e lo vedrai.

Inoltre (anche se userei l'aritmetica al posto di una mappa) la mappa è costante, quindi potrebbe essere costruita prima del tempo e condivisa invece di essere costruita come parte dell'algoritmo di conversione.

Se lo spostamento stesso comporta un ciclo, allora come altri stanno sottolineando, questo finisce per essere un ciclo doppiamente annidato. Tuttavia, il numero di cifre e bit non è probabile che sia abbastanza grande da fare la differenza, a meno che non sia possibile ottenere da migliaia a milioni di cifre.

Inoltre, il numero di iterazioni del ciclo interno, supponendo che utilizziate internamente a 64 bit internamente, sarebbe la dimensione del valore corrente del log di conversione in corso 64, quindi non quello sbagliato IMHO.

Tuttavia, per indirizzare il ciclo interno, è possibile convertire gruppi di 16 cifre alla volta in numeri interi a 64 bit e quindi accumularli nel numero intero grande (quindi è sufficiente eseguire un grande numero intero maiuscole ogni 16 cifre ) ...

    
risposta data 06.02.2017 - 15:02
fonte
1

Il tempo di esecuzione è quadratico nel numero di cifre senza alcuna necessità. Considerando che anche la moltiplicazione e la divisione possono essere fatte molto più velocemente, è piuttosto brutto.

    
risposta data 06.02.2017 - 12:24
fonte

Leggi altre domande sui tag