2015-09-27 7 views

risposta

3

Io non penso c'è un modo semplice per farlo, poiché è necessario conoscere la posizione del punto decimale in tutti i numeri prima di iniziare a stamparli. (Ho appena dato un'occhiata al link di Caramiriel e ad alcuni link da quella pagina, ma non sono riuscito a trovare nulla di particolarmente applicabile a questo caso).

Quindi sembra che si debba eseguire un'ispezione basata su stringhe & manipolazione dei numeri nell'elenco. Ad esempio,

def dot_aligned(seq): 
    snums = [str(n) for n in seq] 
    dots = [s.find('.') for s in snums] 
    m = max(dots) 
    return [' '*(m - d) + s for s, d in zip(snums, dots)] 

nums = [4.8, 49.723, 456.781, -72.18] 

for s in dot_aligned(nums): 
    print(s) 

uscita

4.8 
49.723 
456.781 
-72.18 

Se si desidera gestire un elenco di float s con qualche pianura int s mista in, allora questo approccio diventa un po 'disordinata.

def dot_aligned(seq): 
    snums = [str(n) for n in seq] 
    dots = [] 
    for s in snums: 
     p = s.find('.') 
     if p == -1: 
      p = len(s) 
     dots.append(p) 
    m = max(dots) 
    return [' '*(m - d) + s for s, d in zip(snums, dots)] 

nums = [4.8, 49.723, 456.781, -72.18, 5, 13] 

for s in dot_aligned(nums): 
    print(s) 

uscita

4.8 
49.723 
456.781 
-72.18 
    5 
13 

aggiornamento

Come Mark Ransom note nei commenti, siamo in grado di semplificare la gestione int s utilizzando .split:

def dot_aligned(seq): 
    snums = [str(n) for n in seq] 
    dots = [len(s.split('.', 1)[0]) for s in snums] 
    m = max(dots) 
    return [' '*(m - d) + s for s, d in zip(snums, dots)] 
+0

Invece di 's.find ('. ') 'puoi usare' len (s.split ('. ') [0]) ', che funziona anche con' int'. –

+0

@MarkRansom: Ora perché non ci ho pensato? :) Grazie! –

0

Se si può accettare qualche zero è possibile utilizzare questo:

numbers = [ 4.8, 49.723, 456.781, -72.18] 
    for x in numbers: 
    print "{:10.3f}".format(x) 

Se si preferisce senza zero si potrebbe usare un'espressione regolare in questo modo:

Decimal alignment formatting in Python

Tuttavia il migliore la soluzione dovrebbe essere quella di formattare separatamente la stringa prima e dopo il punto decimale (l'assegnazione numstring):

numbers = [ 4.8, 49.723, 456.781, -72.18] 
nn = [str(X) for X in numbers] 

for i in range(len(nn)): 
    numstring = "{value[0]:>6}.{value[1]:<6}" 
    print numstring.format(value=nn[i].split('.') if '.' in nn[i] else (nn[i], '0')) 

Quindi possiamo dividere la stringa al punto decimale come la parte intera e decimale. Se manca la parte decimale, la assegniamo a 0.

Nota: con questa soluzione è necessario convertire il numero in stringa prima dell'operazione di formattazione.

Questa è l'uscita:

4.8 
49.723 
456.781 
-72.18 

EDIT: Penso che la solution di FeebleOldMan è migliore del mio, si dovrebbe scegliere questo.

2

Fix per cifre decimali

import decimal 

numbers = [4.8, 49.723, 456.781, 50, -72.18, 12345.12345, 5000000000000] 

dp = abs(min([decimal.Decimal(str(number)).as_tuple().exponent for number in numbers])) 
width = max([len(str(int(number))) for number in numbers]) + dp + 1 #including . 

for number in numbers: 
    number = ("{:"+str(width)+"."+str(dp)+"f}").format(number) 
    print number.rstrip('0').rstrip('.') if '.' in number else number 

corretti per tener larghezza in considerazione su richiesta:

numbers = [4.8, 49.723, 456.781, 50, -72.18] 
width = max([len(str(number)) for number in numbers]) + 1 
for number in numbers: 
    number = ("{:"+str(width)+".4f}").format(number) 
    print number.rstrip('0').rstrip('.') if '.' in number else number 

EDIT: Se si desidera includere interi

numbers = [4.8, 49.723, 456.781, 50, -72.18] 

for number in numbers: 
    number = "{:10.4f}".format(number) 
    print number.rstrip('0').rstrip('.') if '.' in number else number 

numbers = [4.8, 49.723, 456.781, -72.18] 

for number in numbers: 
    print "{:10.4f}".format(number).rstrip('0') 
+0

Questa è una soluzione leggera eccellente per quando non ti interessa un offset a sinistra. – mcu

+0

@ coding4fun Ho modificato il codice per tenere conto dell'offset sinistro. – ooknosi

+0

C'è un bug nella tua versione più recente. Provalo con 'numbers = [4.8, 49.723, 456.781, 50, -72.18, 12345.12345]'. Grazie. – mcu

0

È possibile utilizzare il tipo di Python [decimal][1].

C'è un recipe utilizzato per formattare i valori monetari.

Perché decimal Tipo: evitare problemi di arrotondamento, gestire correttamente le cifre signifiant ...

+0

Puoi mostrare un esempio relativo a questa domanda? Non ho capito come formattare correttamente un elenco di numeri allineati al punto decimale usando il tipo decimale. –

+0

Sì, posso (e lo farò), ma hai letto la ricetta? –

+1

Ho capito che era necessario evitare il punto zero. In ogni caso penso che dovresti evitare risposte multiple, come descritto [qui] (http://meta.stackoverflow.com/questions/251070/are-multiple-answers-by-the-same-user-acceptable?rq=1). –

0

Utilizzando la ricetta nella documentazione Python: https://docs.python.org/2/library/decimal.html#recipes

from decimal import Decimal 


def moneyfmt(value, places=3, curr='', sep=',', dp='.', 
      pos='', neg='-', trailneg=''): 
    [...] 

numbers = [4.8, 49.723, 456.781, -72.18] 
for x in numbers: 
    value = moneyfmt(Decimal(x), places=2, pos=" ") 
    print("{0:>10s}".format(value)) 

otterrete:

4.800 
49.723 
456.781 
-72.180 
+0

Hmm, questo codice non funziona per me come è - Python 3.4.3. * TypeError: stringa di formato non vuota passata all'oggetto .__ formato __ * – mcu

+0

Se si utilizza Py3, consultare la documentazione di Py3: https://docs.python.org/3/library/decimal.html#recipes –

0

Sono terribilmente in ritardo, ma puoi anche usare la matematica, in particolare le proprietà dei logaritmi, per calcolare la quantità di spazi che hai ed per riempire tutti i numeri alla posizione decimale corretta.

from math import log10 

nums = [4.8, 49.723, 456.781, -72.18, 5, 13] 

def pre_spaces(nums): 
    absmax = max([abs(max(nums)), abs(min(nums))]) 
    max_predot = int(log10(absmax)) 
    spaces = [' '*(max_predot-int(log10(abs(num))) - (1 if num<0 else 0)) for num in nums] 
    return spaces 

for s,n in zip(pre_spaces(nums), nums): 
    print('{}{}'.format(s,n)) 

Il risultato è:

4.8 
49.723 
456.781 
-72.18 
    5 
13 
Problemi correlati