Eu quero comparar dois números de ponto flutuante em um script de shell. O código a seguir não está funcionando:
#!/bin/bash
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo $min
shell
shell-script
arithmetic
RIchard Williams
fonte
fonte
0.5
e0.06
). É melhor usar uma ferramenta que já entenda a notação decimal.1.00000000000000000000000001
é maior que2
.O Bash não entende a aritmética de ponto flutuante. Ele trata números que contêm um ponto decimal como seqüências de caracteres.
Use awk ou bc.
Se você pretende fazer muitas operações matemáticas, provavelmente é melhor confiar em python ou perl.
fonte
Você pode usar o pacote num-utils para manipulações simples ...
Para matemática mais séria, consulte este link ... Ele descreve várias opções, por exemplo.
Um exemplo de
numprocess
Aqui está um
bash
hack ... Ele adiciona zeros iniciais ao número inteiro para tornar significativa uma comparação da esquerda para a direita. Esse trecho de código específico requer que min e val tenham um ponto decimal e pelo menos um dígito decimal.saída:
fonte
Para cálculos simples em números de ponto flutuante (+ - * / e comparações), você pode usar o awk.
Ou, se você tiver ksh93 ou zsh (não bash), poderá usar a aritmética interna do seu shell, que suporta números de ponto flutuante.
Para cálculos mais avançados de ponto flutuante, procure bc . Na verdade, ele funciona em números de pontos de correção de precisão arbitrária.
Para trabalhar em tabelas de números, procure R ( exemplo ).
fonte
Usar classificação numérica
O comando
sort
possui uma opção-g
(--general-numeric-sort
) que pode ser usada para comparações em<
"menor que" ou>
"maior que", localizando o mínimo ou o máximo.Estes exemplos estão encontrando o mínimo:
Suporta Notação E
Ele funciona com notação bastante geral de números de ponto flutuante, como na Notação E
Observe o
E-10
, tornando o primeiro número0.000000001245
, na verdade menor que10.35
.Pode comparar com o infinito
O padrão de ponto flutuante, IEEE754 , define alguns valores especiais. Para essas comparações, as interessantes são
INF
para o infinito. Há também o infinito negativo; Ambos são valores bem definidos no padrão.Para encontrar o uso máximo em
sort -gr
vez desort -g
, invertendo a ordem de classificação:Operação de comparação
Para implementar a
<
comparação ("menor que"), para que possa ser usada emif
etc, compare o mínimo com um dos valores. Se o mínimo for igual ao valor, comparado como texto , é menor que o outro valor:fonte
a == min(a, b)
é o mesmo quea <= b
. Vale a pena notar que isso não verifica estritamente menos do que no entanto. Se você quiser fazer isso, precisará verificara == min(a, b) && a != max(a, b)
, em outras palavrasa <= b and not a >= b
Basta usar
ksh
(comksh93
precisão) ouzsh
, que suportam nativamente aritmética de ponto flutuante:Edit: Desculpe, eu perdi
ksh93
já foi sugerido. Manter minha resposta apenas para esclarecer o script postado na pergunta de abertura pode ser usada sem alterações fora do switch do shell.Edit2: Observe que
ksh93
exige que o conteúdo da variável seja consistente com o seu código do idioma, ou seja, com um código do idioma francês, uma vírgula em vez de um ponto deve ser usada:Uma solução mais robusta é definir o código do idioma no início do script para garantir que ele funcione independentemente do código do idioma do usuário:
fonte
.
(portanto, não na metade do mundo onde o separador decimal está,
).zsh
não tem esse problema.LC_ALL
, isso também significa que os números não serão exibidos (ou inseridos) no formato preferido do usuário. Consulte unix.stackexchange.com/questions/87745/what-does-lc-all-c-do/… para obter uma abordagem potencialmente melhor..
.Que usa a
dc
calculadora paras
rasgou o valor$min
no registoa
ed
uplicates o valor$val
para o topo de sua principal pilha de execução. Em seguida,l
coloca o conteúdoa
no topo da pilha, quando é parecido com:O
<
aparece no topo duas entradas fora da pilha e compara-los. Portanto, a pilha se parece com:Se a entrada superior for menor que a segunda para cima, ela enviará o conteúdo
a
para a parte superior, para que a pilha se pareça com:Senão, ele não faz nada e a pilha ainda se parece com:
Depois, apenas
p
cria a entrada da pilha superior.Então, para o seu problema:
Mas:
fonte
Por que não usar velho, bom
expr
?Exemplo de sintaxe:
Para expressões verdadeiras , o código de saída expr é 0, com a string '1' enviada para stdout. Inverter para expressões falsas .
Eu verifiquei isso com o GNU e FreeBSD 8 expr.
fonte
expr 1.09 '<' -1.1
imprimirá1
e sairá com0
(sucesso).Para verificar se dois números (possivelmente fracionários) estão em ordem,
sort
é (razoavelmente) portátil:No entanto, se você realmente deseja manter um valor mínimo atualizado, não precisa de um
if
. Classifique os números e use sempre o primeiro (menos):fonte
Normalmente, faço coisas semelhantes com o código python incorporado:
fonte
fonte