Estou procurando uma maneira de dizer ao awk para fazer aritmética de alta precisão em uma operação de substituição. Isso envolve, ler um campo de um arquivo e substituí-lo por um incremento de 1% nesse valor. No entanto, estou perdendo precisão lá. Aqui está uma reprodução simplificada do problema:
$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748
Aqui, tenho 16 dígitos após a precisão decimal, mas o awk fornece apenas seis. Usando printf, estou obtendo o mesmo resultado:
$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16G\n", $1)}'
0.546748
Alguma sugestão de como obter a precisão desejada?
gsub
é desnecessário. O problema é quegsub
funciona em seqüências de caracteres, não em números, portanto, uma conversão é feita primeiroCONVFMT
, e o valor padrão para isso é%.6g
.Respostas:
Ou melhor, aqui:
é provavelmente o melhor que você pode conseguir. Use em
bc
vez disso para precisão arbitrária.fonte
AWK
que você pode usar a-M
bandeira e definir oPREC
valor a um grande númeroPara maior precisão com o (GNU) awk (com o bignum compilado), use:
O PREC = 100 significa 100 bits em vez dos 53 bits padrão.
Se esse awk não estiver disponível, use bc
Ou você precisará aprender a conviver com a imprecisão inerente dos carros alegóricos.
Nas suas linhas originais, existem vários problemas:
O formato de conversão de uma sequência para um número (flutuante) é fornecido pelo CONVFMT. Seu valor padrão é
%.6g
. Isso limita os valores a 6 dígitos decimais (após o ponto). Isso é aplicado ao resultado da alteração gsub de$1
.O formato printf
g
remove zeros à direita:Ambos os problemas podem ser resolvidos com:
Ou
Mas não pense que isso significa maior precisão. A representação interna do número ainda é uma bóia em tamanho duplo. Isso significa 53 bits de precisão e, com isso, você só pode ter certeza de 15 dígitos decimais corretos, mesmo que muitas vezes até 17 dígitos pareçam corretos. Isso é uma miragem.
O valor correto é:
O que também pode ser calculado com (GNU) awk se a biblioteca bignum tiver sido compilada em:
fonte