Converter valor da notação científica para decimal no shell?

2

Como converter um valor de notação científica para decimal no shell? (escudo C preferido)

Também gostaria de convertê-lo de e-12 para e-9 e, em seguida, shell

42,53e-12 a 0,04253. Eu tenho que fazer isso por uma lista.

    
por cHiRaG 11.02.2018 / 22:03

3 respostas

5

printf fará isso por você, do shell.

 $ FOO=42.53e-12
 $ BAR=$(printf "%.14f" $FOO)
 $ echo $BAR
 0.00000000004253
 $

Na antiga C-shell arcana, isso seria.

$ set FOO=42.53e-12
$ set BAR='printf "%.14f" $FOO'
$ echo $BAR
0.00000000004253
$
    
por 11.02.2018 / 22:27
0

Pode não ser a melhor solução, mas consegui fazer isso com um pequeno hack. Você pode fazer algo assim -

scientific='42.53e-12'
base=$(echo $scientific | cut -d 'e' -f1)
exp=$(($(echo $scientific | cut -d 'e' -f2)*1))
converted=$(bc -l <<< "$base*(10^$exp)")
>> .00000000004253000000
    
por 20.10.2018 / 18:41
0

shell

Muitos shells (especialmente antigos + arcane csh) não entendem a aritmética de ponto flutuante.

Na maioria dos shells há um printf embutido que entende de "formato científico".

$ printf '%5.0f\n' '1e3'
 1000

Mas todos os printf poderiam não fazer matemática:

$ printf '%5.0f\n' '1e3+1e3'
printf: ‘1e3+1e3’: value not completely converted

Existe uma solução em duas etapas para o csh. - Primeiro dia  Converta o número em um decimal com menos de 18 dígitos (para um significativo de 53 bits de um float de 64 bits) [a] :

    % printf "%.18f\n" "42.53e-12"
    0.000000000042530000
  • Segundo
    Multiplique por 1e3 (conforme solicitado) e imprima novamente:

    % printf '%.15f\n' "'printf "%.18f" "42.53e-12"'e3"
    0.000000042530000
    

É claro que printf in csh é um utilitário externo com seu próprio tamanho de float (64 bits?) e pode ser diferente para um sistema operacional diferente.

Ferramentas matemáticas.

Para fazer matemática (além do shell), é natural pensar em bc , mas bc tem suas próprias limitações (não entende o e como expoente, ele precisa ser convertido em 10^ ) . Leia isto .

Mas o awk poderia fazer isso:

% echo 42.53e-12 | awk '{printf("%.15f\n", $1*1e3)}'
0.000000042530000

Não espere mais de 15 dígitos corretos, pois o awk usa um bit 53 significativo. Para ter mais, você precisa da versão GNU do awk com o módulo de precisão arbitrária compilado.

% echo 42.53e-12 | awk -M -v PREC=134 '{printf("%.40g\n", $1*1e3)}'
4.253e-08

Isso é 134 bits binários para (até) 40 dígitos decimais. Como um decimal:

% echo 42.53e-12 | awk -M -v PREC=134 '{printf("%.40f\n", $1*1e3)}'
0.0000000425300000000000000000000000000000

lista

Na sua pergunta, você afirma:

I have to do this for a list.

Mas não dê detalhes de que tipo de lista é. Se a lista estiver dentro de um arquivo (não como uma variável shell) você não precisa de nada de csh (ou qualquer outro shell), exceto para executar isto:

% awk '{printf("%.15f\n", $1*1e3)}' <file

As mesmas limitações de precisão acima ainda se aplicam.

[a] Na verdade, para ser tecnicamente exato, você deve limitar o número de dígitos com o formato %g printf primeiro, então a solução pedantemente correta é uma transformação de três níveis.

Em qualquer shell razoável (ksh, bash, zsh), isso funcionará:

$ bash -c 'printf "%.15f\n" "$(printf "%.18f" "$( printf "%.18g" "42.53e-12")" )e3"'
0.000000042530000

Mas citar um double ' ' é realmente estranho em csh, e csh usa set para atribuir a vars. Em resumo, isso funcionará para csh :

$ csh -c 'set a='printf "%.18g" "42.53e-12"'; set a='printf "%.18f" "$a"'; printf "%.18f\n" "${a}e3"'
0.000000042530000000

Mas eu realmente, realmente! acho que você deve evitar o csh.

    
por 20.10.2018 / 23:07

Tags