Pergunta

este deve ser fácil.

Aqui está minha matriz (em vez de um método de geração de matrizes de testes representativos):

>>> ri = numpy.random.randint
>>> ri2 = lambda x: ''.join(ri(0,9,x).astype('S'))
>>> a = array([float(ri2(x)+ '.' + ri2(y)) for x,y in ri(1,10,(10,2))])
>>> a
array([  7.99914000e+01,   2.08000000e+01,   3.94000000e+02,
         4.66100000e+03,   5.00000000e+00,   1.72575100e+03,
         3.91500000e+02,   1.90610000e+04,   1.16247000e+04,
         3.53920000e+02])

Eu quero uma lista de strings onde ' n'.join (list_o_strings) imprimiria:

   79.9914
   20.8
  394.0
 4661.0
    5.0
 1725.751
  391.5
19061.0
11624.7
  353.92

Eu quero fazer um space bloco para a esquerda e a direita (mas não mais do que o necessário).

Eu quero um zero após o decimal, se isso é tudo o que é depois do decimal.

Eu não quero notação científica.

..e eu não quero perder dígitos significativos. (Em 353.98000000000002, o 2 não é significativo)

Sim, é bom querer ..

Python 2.5 %g, %fx.x, etc. estão confusos para mim, ou não podem fazer isso. Eu não tentei import decimal ainda. Eu não consigo ver isso Numpy também (embora, o array.__str__ e array.__repr__ são decimais alinhados (mas às vezes retornam científicos).

Ah, e a velocidade conta. Estou lidando com grandes matrizes aqui.

Minhas abordagens de solução atuais são:

  1. para str (a) e analisar os suportes de Numpy
  2. para str (e) cada elemento na matriz e dividir ('.') Em seguida, pad e reconstrua
  3. para A.astype ('s'+str (i)) onde eu é o max (len (str (a))), depois pad

Parece que deve haver alguma solução pronta para uso por aí ... (mas não é necessário)

A sugestão superior falha com quando dtype é float64:

>>> a
array([  5.50056103e+02,   6.77383566e+03,   6.01001513e+05,
         3.55425142e+08,   7.07254875e+05,   8.83174744e+02,
         8.22320510e+01,   4.25076609e+08,   6.28662635e+07,
         1.56503068e+02])
>>> ut0 = re.compile(r'(\d)0+$')
>>> thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]
>>> print '\n'.join(thelist)
  550.056103
 6773.835663
601001.513
355425141.8471
707254.875038
  883.174744
   82.232051
425076608.7676
62866263.55
  156.503068
Foi útil?

Solução

Desculpe, mas após uma investigação completa, não consigo encontrar nenhuma maneira de executar a tarefa necessária sem um mínimo de pós-processamento (para retirar os zeros que você não deseja ver); algo como:

import re
ut0 = re.compile(r'(\d)0+$')

thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]

print '\n'.join(thelist)

é rápido e conciso, mas quebra sua restrição de ser "pronta para uso"-é, em vez disso, uma combinação modular de formatação geral (que quase faz o que você quer, mas deixa zero que você deseja se esconder) e um re. para remover zeros traseiros indesejados. Praticamente, acho que faz exatamente o que você precisa, mas suas condições são declaradas, acredito, com restrição demais.

Editar: A pergunta original foi editada para especificar dígitos mais significativos, não requer espaço principal extra além do que é necessário para o maior número e fornecer um novo exemplo (onde minha sugestão anterior, acima, não corresponde à saída desejada). O trabalho de remover o espaço em branco que é comum a um monte de cordas é melhor realizado com textwrap.dedent - Mas isso funciona em uma única string (com linhas novas) enquanto a saída necessária é uma lista de strings. Não tem problema, vamos juntar as linhas, deduzi -las e dividi -las novamente:

import re
import textwrap

a = [  5.50056103e+02,   6.77383566e+03,   6.01001513e+05,
         3.55425142e+08,   7.07254875e+05,   8.83174744e+02,
         8.22320510e+01,   4.25076609e+08,   6.28662635e+07,
         1.56503068e+02]

thelist = textwrap.dedent(
        '\n'.join(ut0.sub(r'\1', "%20f" % x) for x in a)).splitlines()

print '\n'.join(thelist)

emite:

      550.056103
     6773.83566
   601001.513
355425142.0
   707254.875
      883.174744
       82.232051
425076609.0
 62866263.5
      156.503068

Outras dicas

A formatação de string pythons pode imprimir apenas os decimais necessários (com %g) ou usar um conjunto fixo de decimais (com %f). No entanto, você deseja imprimir apenas os decimais necessários, exceto se o número for um número inteiro, você deseja um decimal e isso o torna complexo.

Isso significa que você acabaria com algo como:

def printarr(arr):
    for x in array:
        if math.floor(x) == x:
            res = '%.1f' % x
        else:
            res = '%.10g' % x
        print "%*s" % (15-res.find('.')+len(res), res)

Isso primeiro criará uma string com 1 decimal, se o valor for um número inteiro ou imprimirá com decimais automáticos (mas apenas até 10 números) se não for um número fracionário. Por fim, ele o imprimirá, ajustado para que o ponto decimal seja alinhado.

Provavelmente, porém, Numpy realmente faz o que você quer, porque você normalmente deseja que seja no modo exponencial se for muito longo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top