08 ottobre, 2019

Python, funzioni per stringhe - 2


Il post precedente mancava della formattazione dei numeri floating-point; ecco qui la mia soluzione, poi se ne trovo (o mi viene detto) una migliore cambierò.

Un po' di dati per i tests:

>>> from math import pi
>>> pi
3.141592653589793
>>> Kpi = 1000 * pi
>>> Mpi = 1000 * Kpi
>>> Gpi = 1000 * MPi
>>> Gpi = 1000 * Mpi
>>>


f_f(n, p)
formatta il numero n con p cifre decimali. Fa tutto la funzione format, vedere anche qui.

>>> f_f = lambda n, p : format(n, '.' + str(p) + 'f')
>>> f_f(pi, 4)
'3.1416'
>>> f_f(Kpi, 3)
'3141.593'
>>> f_f(Mpi, 2)
'3141592.65'
>>> f_f(Gpi, 0)
'3141592654'
>>>


Per i numeri troppo grossi o troppo piccolo viene comodo il formato esponenziale, ecco f_e:

>>> f_e = lambda n, p : format(n, '.' + str(p) + 'e')
>>> f_e(pi, 3)
'3.142e+00'
>>> f_e(Kpi, 3)
'3.142e+03'
>>> f_e(Mpi, 4)
'3.1416e+06'
>>> f_e(Gpi, 4)
'3.1416e+09'
>>>


f_E
varia da f_e solo nell'uso di 'E' al posto di 'e':

>>> f_E = lambda n, p : format(n, '.' + str(p) + 'E')
>>> f_E(pi, 4)
'3.1416E+00'
>>> f_E(Kpi, 4)
'3.1416E+03'
>>> f_E(Mpi, 4)
'3.1416E+06'
>>> f_E(Gpi, 4)
'3.1416E+09'
>>>


f_g
e f_G combinano le precedenti in funzione della grandezza (assoluta) del numero:

>>> f_g = lambda n, p : format(n, '.' + str(p) + 'g')
>>> f_g(pi, 4)
'3.142'
>>> f_g(Kpi, 4)
'3142'
>>> f_g(Kpi, 6)
'3141.59'
>>> f_g(Mpi, 4)
'3.142e+06'
>>> f_g(Gpi, 4)
'3.142e+09'
>>>


>>> f_G = lambda n, p : format(n, '.' + str(p) + 'G')
>>> f_G(pi, 4)
'3.142'
>>> f_G(Gpi, 4)
'3.142E+09'
>>>


OK
, da provare in strcat (definita nel post precedente, la riporto per comodità (mia e della REPL)):

>>> strcat = lambda lst, sep : list(map(sep.join, zip(*([iter(map(str, lst))]*(len(lst))))))[0]
>>> strcat(['prova', 1, 2.2, pi, f_f(pi, 2)], ' | ')
'prova | 1 | 2.2 | 3.141592653589793 | 3.14'
>>>


OK
, come previsto, perché...

>>> st = strcat(['perché', 1, 2.2, pi, f_f(pi, 2)], ' | ')
>>> st
'perché | 1 | 2.2 | 3.141592653589793 | 3.14'
>>>


C'è una scuola di pensiero (comprende gli Excellisti, ma non solo) che considera un errore l'uso del punto quale separatore decimale al posto della (canonica) virgola. È semplicissimo accontentarli, cf_f è la versione virgolata di f_f; le altre sono lasciate come esercizio:

>>> cf_f = lambda n, p : format(n, '.' + str(p) + 'f').replace('.', ',')
>>> cf_f(kpi, 2)
'3141,59'
>>>


OK
, questo è tutto. Però, idea, da cosa nasce cosa, si possono costruire in modo affine le funzioni per rappresentare gli interi in binario e esadecimale (qualcuno usa ancora gli ottali o sono rimasto il solo a ricordare che il Prime?):

>>> f_b = lambda n : f'{n:b}'
>>> f_b(15)
'1111'
>>> f_b(255)
'11111111'
>>> f_x = lambda n : f'{n:x}'
>>> f_x(15)
'f'
>>> f_x(255)
'ff'
>>> f_X = lambda n : f'{n:X}'
>>> f_X(255)
'FF'
>>>


Per avere la stringa del valore decimale:

>>> f_d = lambda n : f'{n}'
>>> f_d(0xff)
'255'
>>> f_d(0b11111111)
'255'
>>>

ma probabilmente è più utile il valore:

>>> f_id = lambda n : int(f'{n}')
>>> f_id(0xff)
255
>>>


Naturalmente tutto questo solo per gli interi, altrimenti si ottiene un errore: ValueError: Unknown format code 'X' for object of type 'float'. Sì, si potrebbero gestire, esercizio?

🔴

Nessun commento:

Posta un commento