Por que as versões mais recentes do awk imprimem inteiros grandes em vez de números decimais?

2

Costumo usar a calculadora awk (gawk):

calc(){ awk "BEGIN{ print $* }" ;}

No Ubuntu 14.04, ele gera grandes números em formato padrão, por exemplo

$ calc 56777654409823*4674990588446667952594759939814064128
2.65435e+50

Mas agora (Ubuntu 15.10) a saída nunca está em formato padrão:

$ calc 56777654409823*4674990588446667952594759939814064128
265434999999999985120999032855606532558652107128832

O que mudou? Existe uma maneira de eu escolher se a saída está em formato padrão ou não?

    
por EmmaV 08.04.2016 / 04:10

2 respostas

4

Use printf em vez disso.

calc(){ awk "BEGIN{ printf (\"%.5e\n\", $*) }" ;}
    
por 08.04.2016 / 04:32
3

O que você vê na sua resposta do awk é principalmente o ruído.

Podemos comparar os números com bc um pequeno utilitário (em torno de 80kByte) projetado para fazer cálculos de precisão arbitrária:

$ calc(){ awk "BEGIN{print $*}"; }
$ math='56777654409823*4674990588446667952594759939814064128'
$ bc <<<"$math"; calc "$math"
265434999999999978394292482412066060207814915129344
265434999999999985120999032855606532558652107128832

265434999999999978394292482412066060207814915129344     2654349999999999

85120999032855606532558652107128832

Observe que os únicos números que correspondem são os primeiros ~ 16 dígitos decimais, que é a precisão da matemática de ponto flutuante de precisão dupla (64 bits).

Sim, o gawk poderia executar matemática de precisão arbitrária, mas somente se isso tiver sido compilado no programa e o programa é chamado com o -M .

  • Verifique se o --version contém "GNU MPFR e GNU MP".

    gawk --version
    -| GNU Awk 4.1.2, API: 1.1 (GNU MPFR 3.1.0-p3, GNU MP 5.0.2)
    -| Copyright (C) 1989, 1991-2015 Free Software Foundation.
    
  • chame o gawk com a opção -M .

    Leia 15.5 Aritmética de Precisão Aritmética com Gawk .

Você deve chamar o gawk como:

calc(){ awk -M "BEGIN{print $*}"; }     

Em vez de ter que verificar vários detalhes com o awk ou o gawk, use:

Use bc

bc é um utilitário usado para fazer matemática com precisão arbitrária:

bc <<<'56777654409823*4674990588446667952594759939814064128'
265434999999999978394292482412066060207814915129344

Calcule pi a 200 dígitos (4 vezes o arco tangente de 1):

$ bc <<<"scale=200;4*a(1)"
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
223172535940812848111745028410270193852110555964462294895493038196

use o cálculo real:

Após sua função definida, você verá esta lista se escrever:

$ type -a calc
calc is a function
calc () { awk -M "BEGIN{print $*}"; }
calc is /usr/bin/calc

apenas undefine a função:

$ unset -f calc
$ type calc
calc is /usr/bin/calc

Lá você poderia fazer:

$ calc '2* 3'
6

$ calc '2 ^ 127 - 1'   # mersene prime.
170141183460469231731687303715884105727

$ calc '56777654409823*4674990588446667952594759939814064128'
         265434999999999978394292482412066060207814915129344

Qual é exatamente a mesma resposta de bc:

$ math='56777654409823*4674990588446667952594759939814064128'
$ bc <<<"$math"; echo $(calc "$math")
265434999999999978394292482412066060207814915129344
265434999999999978394292482412066060207814915129344
    
por 06.10.2016 / 02:16