Successivo: Problemi virgola mobile POSIX, Precedente: Cautela col calcolo in VM, Su: Calcolo con precisione arbitraria [Contenuti][Indice]
gawk
Quando viene specificata l’opzione -M,
gawk
esegue tutti i calcoli sui numeri interi usando gli interi a
precisione arbitraria della libreria GMP. Qualsiasi numero che appaia come un
intero in un sorgente o in un file-dati è memorizzato come intero a precisione
arbitraria. La dimensione del numero intero ha come limite solo la memoria
disponibile. Per esempio, il seguente programma calcola
5432,
il cui risultato è oltre i limiti degli ordinari valori a virgola mobile a
doppia precisione dei processori:
$ gawk -M 'BEGIN { > x = 5^4^3^2 > print "numero di cifre =", length(x) > print substr(x, 1, 20), "...", substr(x, length(x) - 19, 20) > }' -| numero di cifre = 183231 -| 62060698786608744707 ... 92256259918212890625
Se invece si dovesse calcolare lo stesso valore usando valori a virgola mobile con precisione arbitraria, la precisione necessaria per il risultato corretto (usando la formula ‘prec = 3.322 * dps’) sarebbe 3.322 x 183231, o 608693.
Il risultato di un’operazione aritmetica tra un intero e un valore a virgola mobile è un valore a virgola mobile con precisione uguale alla precisione di lavoro. Il seguente programma calcola l’ottavo termine nella successione di Sylvester104 usando una ricorrenza:
$ gawk -M 'BEGIN { > s = 2.0 > for (i = 1; i <= 7; i++) > s = s * (s - 1) + 1 > print s > }' -| 113423713055421845118910464
Il risultato mostrato differisce dal numero effettivo, 113.423.713.055.421.844.361.000.443, perché la precisione di default di 53 bit non è suffciente per rappresentare esattamente il risultato in virgola mobile. Si può o aumentare la precisione (in questo caso bastano 100 bit), o sostituire la costante in virgola mobile ‘2.0’ con un intero, per eseguire tutti i calcoli usando l’aritmetica con gli interi per ottenere l’output corretto.
A volte gawk
deve convertire implicitamente un intero con precisione
arbitraria in un valore a virgola mobile con precisione arbitraria.
Ciò si rende necessario
principalmente perché la libreria MPFR non sempre prevede l’interfaccia
necessaria per elaborare interi a precisione arbitraria o numeri di tipo
eterogeneo come richiesto da un’operazione o funzione. In tal caso, la
precisione viene impostata al minimo valore necessario per una conversione
esatta, e non viene usata la precisione di lavoro. Se
questo non è quello di cui si ha bisogno o che si vuole, si può ricorrere a un
sotterfugio e convertire preventivamente l’intero in un valore a virgola
mobile, come qui di seguito:
gawk -M 'BEGIN { n = 13; print (n + 0.0) % 2.0 }'
Si può evitare completamente questo passaggio specificando il numero come valore a virgola mobile fin dall’inizio:
gawk -M 'BEGIN { n = 13.0; print n % 2.0 }'
Si noti che, per questo specifico esempio, probabilmente è meglio semplicemente specificare:
gawk -M 'BEGIN { n = 13; print n % 2 }'
Dividendo due interi a precisione arbitraria con ‘/’ o con ‘%’, il
risultato è tipicamente un valore a virgola mobile con precisione arbitraria
(a meno che il risultato non sia un numero intero esatto).
Per eseguire divisioni intere o calcolare moduli con interi a precisione
arbitraria, usare la funzione predefinita
intdiv()
(vedi Funzioni numeriche).
Si può simulare la funzione intdiv()
in awk
standard
usando questa funzione definita dall’utente:
# intdiv --- fa una divisione intera function intdiv(numerator, denominator, result) { split("", result) numerator = int(numerator) denominator = int(denominator) result["quotient"] = int(numerator / denominator) result["remainder"] = int(numerator % denominator) return 0.0 }
Il seguente programma d’esempio, proposto da Katie Wasserman,
usa intdiv()
per
calcolare le cifre di pi al numero di cifre significative
che si è scelto di impostare:
# pi.awk --- calcola le cifre di pi BEGIN { cifre = 100000 due = 2 * 10 ^ cifre pi = due for (m = cifre * 4; m > 0; --m) { d = m * 2 + 1 x = pi * m intdiv(x, d, risultato) pi = risultato["quotient"] pi = pi + due } print pi }
Quando gli fu chiesto dell’algoritmo usato, Katie rispose:
Non è quello più noto ma nemmeno quello più incomprensibile. È la variante di Eulero al metodo di Newton per il calcolo del Pi greco. Si vedano le righe (23) - (25) nel sito: http://mathworld.wolfram.com/PiFormulas.html.
L’algoritmo che ho scritto semplicemente espande il moltiplicare per 2 e lavora dall’espressione più interna verso l’esterno. Ho usato questo per programmare delle calcolatrici HP perché è piuttosto facile da adattare ai dispositivi di scarsa memoria con dimensioni di parola piuttosto piccole. Si veda http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/articles.cgi?read=899.
Weisstein, Eric W. Sylvester’s Sequence. From MathWorld—A Wolfram Web Resource (http://mathworld.wolfram.com/SylvestersSequence.html).
Successivo: Problemi virgola mobile POSIX, Precedente: Cautela col calcolo in VM, Su: Calcolo con precisione arbitraria [Contenuti][Indice]