Você pode usar o Zsh .
A maioria dos shells, incluindo Bash, não suportam diretamente cálculos de ponto flutuante e como Oli explicou , a solução típica é chamar bc
. No entanto, você tem um número de outras opções .
Um deles é usar o Z Shell . zsh
é um Shell estilo shell ( mesma" família " como Bash) que suporta diretamente computações de ponto flutuante. Então, se você estiver disposto a criar um script Zsh em vez de um script Bash, poderá fazer isso alterando a primeira linha do script de #!/bin/bash
para #!/bin/zsh
.
Assim que fizer isso, funcionará automaticamente! Neste caso , nenhuma modificação adicional no script é necessária. (Às vezes, um recurso Bash e o recurso Zsh correspondente funcionam de modo diferente, portanto, traduzir um script de Bash para Zsh exige que você faça alterações. Embora às vezes um script Bash com erros possa ser correto > quando tratado como um script Zsh, devido a diferentes decisões de design no Zsh sobre o que expansions deve ser executado automaticamente.
Esta é a saída:
9
0.5000000000 + 1.5000000000
1.5000000000 + 2.5000000000
2.5000000000 + 3.5000000000
3.5000000000 + 4.5000000000
4.5000000000 + 5.5000000000
5.5000000000 + 6.5000000000
6.5000000000 + 7.5000000000
7.5000000000 + 8.5000000000
8.5000000000 + 9.5000000000
9.5000000000 + 10.5000000000
Você precisará do Zsh instalado para ser executado. O Zsh geralmente não vem pré-instalado no Ubuntu, mas é fornecido pelo pacote zsh
. Se você não tiver zsh
, verá um erro como:
-bash: ./your-script: /bin/zsh: bad interpreter: No such file or directory
O pacote zsh
do Ubuntu oferece /bin/zsh
e /usr/bin/zsh
. Se você quer que seu script seja portável para outros sistemas que tenham Zsh mas em lugares diferentes, então você pode querer usar este hashbang line no topo do seu script:
#!/usr/bin/env zsh
Se o usuário puder executar o Zsh digitando zsh
e pressionando Enter , então colocar isso no início de um script normalmente funcionará (e executará o mesmo executável zsh
que o usuário executaria ). Isso não funciona em 100% dos sistemas - tecnicamente, env
em si não tem que ser fornecido em /usr/bin
- mas na prática é bastante raro para ele falhar, desde que zsh
esteja no usuário $PATH
.
Para mais informações sobre avaliação aritmética em Zsh, incluindo aritmética de ponto flutuante, veja 11 Avaliação aritmética no Manual do Z Shell .
Diminuindo a precisão da saída
Uma variável de ponto flutuante x
em Zsh pode mostrar mais precisão do que você deseja quando você a expande como $x
:
% ((x=.5))
% echo "$x"
0.5000000000
Uma maneira de expandi-lo sem esses zeros extras é usar a expansão aritmética:
% echo "$((x))"
0.5
Você também pode usar o comando printf
para exibir um valor com precisão limitada:
% printf '%.2f\n' "$x"
0.50
Isso funciona em outros shells também, mesmo quando o shell não suporta aritmética de ponto flutuante. (Algumas shells não têm um printf
embutido, mas você ainda pode usar esse comando porque uma versão executável independente está instalada em /usr/bin/printf
.) O comando printf
não irá executar outra aritmética, além do arredondamento.
Mesmo em situações em que você não precisa de formatação numérica, printf
é geralmente uma escolha melhor que echo
em scripts de shell .
Caso você esteja interessado, o manual do Zsh (como mencionado acima) explica como precisamente os valores de ponto flutuantes são realmente armazenados. (Geralmente é IEEE 754 binary64 .)
Você pode usar uma sintaxe mais simples (no Bash também).
Seu script está bem, mas você pode simplificar sua sintaxe para melhorar a legibilidade:
- Seu script não precisa de o agrupamento fornecido por
{
e }
.
- Um
;
é redundante no final de uma linha.
- Por dentro de
((
))
, $i
pode ser apenas escrito i
.
- Você pode usar
((
))
em vez de let
. Sem um $
inicial, ele avalia sem se expandir para o resultado. Nem todos os shells suportam este formulário de não expansão, mas Bash e Zsh (e alguns outros) fazem isso.
-
É bom citar quando você não quer que a divisão de palavras ocorra mesmo quando isso é opcional (como neste caso). Mas você pode incluir mais de uma expansão no mesmo intervalo de texto com aspas duplas.
Deixando de fora o pouco sobre n
no começo (você pode muito bem precisar disso para o seu propósito, mas não sei dizer para que serve), eu sugiro:
#!/bin/zsh
for ((i = .5; i < 10; i++))
do
((c = i + 1))
echo "$i + $c"
done
Ou, se você não quiser que esses zeros extras sejam impressos:
#!/bin/zsh
for ((i = .5; i < 10; i++))
do
echo "$((i)) + $((i + 1))"
done
Isto imprime:
0.5 + 1.5
1.5 + 2.5
2.5 + 3.5
3.5 + 4.5
4.5 + 5.5
5.5 + 6.5
6.5 + 7.5
7.5 + 8.5
8.5 + 9.5
9.5 + 10.5
Finalmente, para abordar um ponto de possível confusão:
- Não há problema em atribuir
i
com i = .5
, porque isso foi avaliado como uma expressão aritmética, devido a aparecer dentro de ((
))
e, portanto, espaços em torno de =
foram permitidos. Os espaços não são necessários e você não precisa usá-los, mas pode fazê-lo. (Eu fiz isso.)
-
Fora de uma expressão aritmética, atribuir uma variável shell requer que não haja espaços em ambos os lados de
=
. Ou seja, normalmente você deve escrever var=val
, não var = val
. Da mesma forma, fora de uma expressão aritmética, acessando o valor de uma variável de shell requer $
(por exemplo, $i
, ${i}
).