Formatação de decimal para exponencial

1

Eu tenho um arquivo de dados abc.txt no seguinte formato:

BALT 1
 54.500 -161.070
 3.95863757
 0.01691576
BARM 2
 -9.200 67.120
 4.07529868
 0.01951653
BKSR 3
 43.830 142.520
 4.08919819
 0.00587340

Eu preciso convertê-lo no formato:

BALT 1
 54.5000000 -161.070000
 0.3958637E+01
 0.1691576E-01
BARM 2
 -9.20000000 67.1200000
 0.4075298E+01
 0.1951653E-01
BKSR 3
 43.8300000 142.520000
 0.4089198E+01
 0.5873400E-02

O espaço total ocupado pelos números na segunda linha deve ser 10, excluindo o sinal -ve (por exemplo, 54.500 como 54.5000000 e -161.070 como -161.070000). Os espaços para a 3ª e 4ª linhas devem ser 13 (por exemplo, 3,95863757 como 0,3958637E + 01). E BALT ou BARM são variáveis, pode ser outra palavra com quatro caracteres.

Thank you.

    
por Abhay 08.11.2015 / 08:15

3 respostas

2

versão 3 use um arquivo awk como

function tenth(x) {
  u = x ; if ( u < 0 ) u = -x ;
  b=10 ;
  a=b-2 ;
  if ( u >= 10 ) {
  d=int(log(u)/log(10)) ;
  a=b-d-1 ;
  }
  printf "%*.*f",b,a,x ;
}
length($1) == 4 { print ; next  ;}
NF == 1 { d=int(log($1)/log(10)) ;if (d> -1) d++ ; printf " %.7fE%+03d\n",$1/(10^d),d ;}
NF == 2 { printf " " ; tenth($1); printf " " ; tenth($2) ; printf "\n" ;}

onde

  • lengtht$1) == 4 { print ; next ;} deixará a linha sozinha, onde o primeiro campo é quatro letras (que pode ser 1234)
  • function tenth(x) : define uma função que ajusta a formatação.
  • "%*.*f" string ajusta o tamanho / precisão de %f conversion. primeiro * é substituído por b, segundo * é substituído por um.
  • int(log()/log(10)) dá um log decimal que ajusta a representação para sua necessidade específica?

use-o com

awk -f f.awk input

que dão como resultado

BALT 1
 54.5000000 -161.070000
 0.3958638E+01
 0.1691576E-01
BALT 2
 -9.20000000 67.1200000
 0.4075299E+01
 0.1951653E-01
BALT 3
 43.8300000 142.520000
 0.4089198E+01
 0.5873400E-02
 0.00000000 1.00000000
 -3.14150000 2.71828183
    
por 08.11.2015 / 08:49
0

Talvez algo como:

awk '
  !/[[:alpha:]]/{
    if (NF == 1)
      $0 = sprintf(" %.7E", $0 * 10)
    else
      $0 = sprintf(" %.8f %.8f", $1, $2)
  }
  {print}' | sed '
    s/\([0-9.]\{10\}\)[0-9]*//g
    s/\([1-9]\)\.\(.*\).E/0.E/'
    
por 08.11.2015 / 17:21
-1

Você pode obtê-lo sem o awk com:

while read line; do echo $line; read a; read b; read c;  printf "%.7f %.7f\n %.7e\n %.7e\n" $a $b $c; done < data.txt

No entanto, o uso do printf dessa maneira pode levar a alguns problemas se você estiver usando alguma localidade usando vírgula em vez de ponto final. Nesse caso, você deve conseguir corrigi-lo com:

while read line; do echo $line; read a; read b; read c; LC_NUMERIC="en_US.UTF-8" printf "%.7f %.7f\n %.7e\n %.7e\n" $a $b $c; done < data.txt

Claro que, em um script, você deve formatá-lo melhor com retorno e recuo de carro.

    
por 08.11.2015 / 10:26