Ancora sui numeri grossi, ma anche piccoli

A volte ritornano! Chi? Cosa? Quello che volete, quello che non vi aspettate; per esempio oggi torna l’argomento già trattato nel post “Numeri grossi“.

Anche se, pare, non sia un argomento interessante. Ma interessa me a allora… 8)
Ci metto anche una dritta su Unix/Linux che tanti giudicheranno banale e elementare ma metti che uno inizi adesso –come me 8). (Sì a volte dico bugie ma mi hanno insegnato che le bugie si possono dire a fin di bene 😉 ).

Il post precedente finiva con la constatazione che per numeri davvero grandi la rappresentazione normale è insufficiente, così

Propongo di fare come fanno i matematici e gli scienziati (e anche gli ing.): ricorriamo alla rappresentazione esponenziale: il numero mille viene scritto come 1e3, cioè 1*103; il numero un miliardo diventa 1e9.

Facile e efficace vero? C’è da dire che non a tutti piace e c’è un’alternativa, più usata dalle persone sane di mente e normali, talmente comune che non ci accorgiamo nemmeno di usarla. Sto parlando dei prefissi di SI (Sistema internazionale di unità di misura).
Quando diciamo kilometro, milligrammo, ettolitro, nanometro e simili stiamo usando SI.
E quando diciamo che il disco fisso (hard disk) del nostro computer è di 200 gigabytes usiamo ‘quasi’ SI. Sì perché in questo caso il fattore di moltiplicazione non è 1000 ma 210 = 1024, vedi qui.

Tornando al nostro problema vediamo di riciclare gli script Python e bash aggiornandoli a rappresentare i numeri anche in formato esponenziale.

Ormai siamo abituati a scrivere j1 3^50 e deve essere possibile continuare a farlo ma se scriviamo j1 -e 3^50 vogliamo la rappresentazione esponenziale.

Vediamo intanto come dobbiamo modificare lo script bash, propongo di chiamarlo jp1, eccolo

#!/bin/sh
par="calc "
xp=""

for c in $*
do
    if [ "$c" = "-e" ]; then
        xp="E"
    else
        par=$par\ $c
    fi
done

#echo $xp $par
./j30.py $xp `$par`

Semplice vero? Esegue un ciclo for per i parametri passati nella riga di comando ($*) accumulandoli nella variabile par ad eccezione di -e che viene memorizzato in xp.

Lo script di Python (adesso j30.py) viene anch’esso modificatto, così

#!/usr/bin/env python

import sys

#print sys.argv
if len(sys.argv) == 0:
    print 0
else:
    if sys.argv[1] == 'E':
        arg = sys.argv[2]
        xp = True
        fmt = '{:,e}'
    else:
        arg = sys.argv[1]
        xp = False
        fmt = '{:,}'
    try:
        if arg[0] == '~': arg = arg[1:]
        d = arg.find('.')
        if d >= 0:
            st = fmt.format(float(arg))
        else:
            st = fmt.format(long(arg))
    except:
        print 'error'
        sys.exit(1)

    if xp: d = st.find('.')
    p = st.find('.')
    if d >= 0:
        st = st[:p] + '@' + st[p+1:]
    q = st.find(',')
    while q > 0:
        st = st[:q] + '.' + st[q+1:]
        q = st.find(',')
    if d >= 0:
        st = st[:p] + ',' + st[p+1:]
    print st

Il formato di formattazione dell’istruzione format lo prendiamo sempre dalla documentazione online.

Entrambi gli script hanno un’istruzione commentata, (righe 14 e 5) molto utile in fase di debug. Per questo le ho lasciate, non si sa mai.

Notare come adesso la rappresentazione esponenziale sia utile anche per la rappresentazione di numeri molto piccoli, prossimi a zero, così

Ma non troppo piccoli


E abbiamo ancora un problema con i numeri negativi

perché il segno “” viene interpretato come introduzione di un’opzione. Sarebbe da correggere, lasciato come compito per il lettore (compito delle vacanze). A meno che … No per adesso un altro post non è previsto 8)

Resta ancora un passo da fare: rendere il comando jp eseguibile indipendentemente dalla directory in cui ci troviamo, come i comandi seri ls, echo, cat

Come qualcuno sa c’è una directory speciale nella nostra home, è la directory ~/bin. Il carattere “~” si ottiene con AltGr+ì con la tastiera italiana. Per vedere se c’è basta fare così


OK, io ho ~/bin e non ~/bon.

Se ~/bin è presente viene automaticamente inserita nella PATH, si può verificare con


Nel caso in cui non esista si può creare, così (N.B.: io creo ~/bon, per quando detto sopra)

A questo punto copiamo il file j30.py in ~/bin


Lo script jp1 dev’essere leggermente modificato, inoltre lo salvo come jp

#!/bin/sh
par="calc "
xp=""

for c in $*
do
    if [ "$c" = "-e" ]; then
        xp="E"
    else
        par=$par\ $c
    fi
done

#echo $xp $par
~/bin/j30.py $xp `$par`

e lo copio in ~/bin


D’ora in poi il comando sarà eseguibile da ogni directory


Attenzione: se avete creato la directory ~/bin questa sarà inserita nella PATH al prossimo avvio o reset. OK, ci sarebbe ancora qualcosa da dire ma per iniziare credo sia sufficiente.

_____________
Un piccolo aneddoto: mentre stavo preparando il post (in particolare lo script bash) sono incappato in uno di quegli errori banalissimi quando li fa un altro ma se lo fai tu e sei solo e ti intestardisci non lo trovi e dai di matto brutto.
Potenza di Google+: ho postato il problema e la soluzione è arrivata in pochi minuti, qui 8)

Un amico vale un tesoro, io ne avevo due online, di quelli tosti 8)

Posta un commento o usa questo indirizzo per il trackback.

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: