Che cos'è questo algoritmo per convertire stringhe in numeri chiamati?

5

Recentemente ho lavorato un po 'su Parsec, e per il mio linguaggio giocattolo volevo che fossero espressi numeri frazionari multi-base. Dopo aver scavato un po 'nella fonte di Parsec, ho trovato la loro implementazione di un parser in virgola mobile e l'ho copiato per apportare le modifiche necessarie.

Quindi capisco cosa fa questo codice, e vagamente perché (non ho ancora elaborato completamente la matematica, ma penso di aver capito il senso). Ma da dove è venuto? Questo sembra un modo abbastanza intelligente per trasformare le stringhe in float e int, c'è un nome per questo algoritmo? O è solo qualcosa di fondamentale che è un buco nella mia conoscenza? La gente dietro a Parsec l'ha ideata?

Ecco il codice, prima per i numeri interi:

number' :: Integer -> Parser Integer                                        
number' base = 
    do { digits <- many1 ( oneOf ( sigilRange base ))
       ; let n = foldl (\x d -> base * x + toInteger (convertDigit base d)) 0 digits
       ; seq n (return n)
       }

Quindi l'idea di base è che digits contenga la stringa che rappresenta l'intera parte del numero, ovvero "192" . Il foldl converte ogni cifra singolarmente in un numero, quindi la aggiunge al totale parziale moltiplicato per la base, il che significa che alla fine ogni cifra è stata moltiplicata per il fattore corretto (in aggregato) per posizionarla.

La parte frazionaria è ancora più interessante:

fraction' :: Integer -> Parser Double
fraction' base =
    do { digits <- many1 ( oneOf ( sigilRange base ))
       ; let base' = fromIntegral base
       ; let f = foldr (\d x -> (x + fromIntegral (convertDigit base d))/base') 0.0 digits
       ; seq f (return f)

La stessa idea generale, ma ora foldr e utilizzo della divisione ripetuta. Non capisco perché prima si aggiunge e poi si divide per la frazione, ma prima si moltiplica e poi si aggiunge per il tutto. So che funziona, ma non ho risolto il motivo.

Ad ogni modo, mi sento stupido a non lavorarci da solo, è molto semplice e intelligente guardarlo. C'è un nome per questo algoritmo? Forse la versione imperativa che utilizza un ciclo sarebbe più familiare?

    
posta CodexArcanum 05.04.2012 - 16:44
fonte

3 risposte

7

In realtà non è così intelligente, ma piuttosto solo una conseguenza di come funziona il sistema decimale. Può sembrare un po 'insolito in Haskell perché i loop sono espressi come pieghe, ma l'algoritmo di base è praticamente il modo più diretto che si possa fare su questo (eccetto per i fattori di cifre hard-coding, che sono brutti e cattivi in così tanti modi).

Quindi dubito che qualcuno si sia preso la briga di nominare questo algoritmo, davvero.

    
risposta data 05.04.2012 - 17:24
fonte
3

Questa è un'applicazione del metodo Horner per la valutazione dei polinomi. Si basa sull'osservazione che un numero abcdef in un sistema numerale posizionale con base k è il polinomio a*x^5+b*x^4+...+f*x^0 valutato a x=k .

Per quanto riguarda il motivo per cui esiste un'asimmetria tra l'intero e le parti frazionarie, ciò rispecchia semplicemente l'asimmetria tra gli esponenti 0, 1, 2, ... da un lato e -1, -2, ... senza lo zero sull'altro.

    
risposta data 29.07.2013 - 21:57
fonte
1

Il mio Haskell è molto arrugginito, ma, da quello che vedo, questo è il solito metodo facile e veloce per convertire una stringa in un numero in virgola mobile. Veloce e facile, ma non un buon metodo per il codice di produzione che richiede numeri precisi. Ogni divisione per ogni cifra nella frazione causa una potenziale perdita di IIRC, 1/2 del bit meno significativo della mantissa in accuratezza. Non ho familiarità con gli interni delle librerie Unix e Windows, ma ricordo di aver visto la microfiche per le porzioni delle librerie matematiche VAX / VMS negli anni '80 e hanno usato, sempre se ricordo male, aritmetica a 128 bit implementata dal software (che non era supportato in quel momento nell'hardware) per garantire l'accuratezza dei loro risultati man mano che i calcoli progredivano.

    
risposta data 03.10.2015 - 01:23
fonte

Leggi altre domande sui tag