Como arredondar corretamente os números de ponto flutuante IEEE 754 na linha de comando?
Quero especificar a precisão do número de saída - a contagem de dígitos fracionários.
O arredondamento 6.66
para a precisão 1
deve fornecer 6.7
, por exemplo. Mais na tabela abaixo:
Value Precision Rounded
6.66 0 7
6.66 1 6.7
6.66 2 6.66
6.66 3 6.660
6.666 3 6.666
6.6666 3 6.667
Deve ser utilizável em um shell interativo, mas idealmente robusto o suficiente para usá-lo em scripts de shell de produção.
bash
command-line
arithmetic
floating-point
Volker Siegel
fonte
fonte
awk
.Respostas:
Arredondando números de ponto flutuante
O que significa "arredondar um número de ponto flutuante"?
Isso é fácil, obviamente ... Onde está o meu livro de matemática da escola ...
Não, já sabemos que nada relacionado a números de ponto flutuante é fácil:
Para começar, existem vários modos de arredondamento:
Como lidar com os casos de canto? Como descobrir quais são os casos de canto?
OK, parece que é melhor usarmos uma implementação do padrão IEEE 754 e deixar nosso sistema cuidar disso.
Para arredondar um número de ponto flutuante no shell, com base na aritmética padrão de ponto flutuante, precisamos de três etapas:
Acontece que o comando shell
printf
pode fazer tudo isso. Ele pode ser usado para imprimir números de acordo com uma especificação de formato, conforme descrito emman 3 printf
. Os números são arredondados implicitamente da maneira padrão, se necessário para o formato de saída:O comando
Arredonde
x
parap
precisão de dígitos com entrada como argumentos de linha de comando:Ou em um pipeline de shell, com entrada de
x
entrada padrão ep
como argumento:Exemplos:
Armadilhas ruins
Cuidado com o local! Ele especifica o separador entre a parte integral e a fração - o
.
, como você pode esperar.Mas veja o que acontece em um código de idioma alemão, por exemplo:
Sim, está certo
6,667
- seis vírgulas seis seis sete. Isso atrapalharia o seu script, com certeza.(Mas apenas para os dois clientes na Alemanha. Exceto pelas máquinas do desenvolvedor atualmente depurando para esses clientes.)
Mais robusto
Para torná-lo mais robusto, use:
ou
Isso também usa, em
/usr/bin/printf
vez do shell internobash
ouzsh
para solucionar pequenas inconsistências na implementação dasprintf
variantes, e evita um efeito muito sujo quando, em um código de idioma alemão,LC_ALL
é definido, mas não exportado. Então, o builtin usa,
, e/usr/bin/printf
usa.
...Consulte também
%g
para arredondar para um número especificado de dígitos significativos.fonte
A seguir funcionou para mim.
fonte