Estou tentando dividir duas larguras de imagem em um script Bash, mas o bash me fornece 0
o resultado:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
Estudei o guia Bash e sei que devo usar bc
, em todos os exemplos na internet que eles usam bc
. Em echo
Tentei colocar a mesma coisa na minha SCALE
, mas não funcionou.
Aqui está o exemplo que encontrei nos tutoriais:
echo "scale=2; ${userinput}" | bc
Como faço para que o Bash me dê um float como 0.5
?
bash
floating-point
arithmetic-expressions
Medya Gh
fonte
fonte
Respostas:
Você não pode. festa única faz inteiros; você deve delegar para uma ferramenta como
bc
.fonte
VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)
ouVAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")
sem $ (()) (parênteses duplos); que se expandiu pela festa antes do comando executarvocê consegue fazer isso:
UPDATE
20130926
: você pode usar:fonte
bc -l <<< 'scale=2; 100/3'
Unless specifically mentioned the scale of the result is the maximum scale of the expressions involved.
E há uma nota extra para/
operador:The scale of the result is the value of the variable scale.
bc <<< 'scale=1; 1*3.00001'
escala é realmente 5 por algum motivo,bc <<< 'scale=1; 1/3.000001'
escala é 1. Curiosamente, dividir por 1 ajusta-a: abc <<< 'scale=1; 1*3.00001/1'
escala é 1festança
Conforme observado por outros,
bash
não suporta aritmética de ponto flutuante, embora você possa falsificá-lo com alguns truques decimais fixos, por exemplo, com dois decimais:Resultado:
Veja a resposta de Nilfred para uma abordagem semelhante, porém mais concisa.
Alternativas
Além dos mencionados
bc
e dasawk
alternativas, existem também os seguintes:clisp
com saída limpa:
ou através de stdin:
dc
calculadora gênio cli
ghostscript
gnuplot
jq
Ou:
ksh
lua
ou através de stdin:
maxima
com saída limpa:
nó
oitava
perl
python2
python3
R
com saída limpa:
rubi
wcalc
Com saída limpa:
zsh
unidades
Com saída compacta:
Outras fontes
Stéphane Chazelas respondeu a uma pergunta semelhante no Unix.SX.
fonte
echo 1/3 | node -p
é curto.Melhorando um pouco a resposta de marvin:
O bc nem sempre vem como pacote instalado.
fonte
exit
para impedir a leitura do fluxo de entrada. Sugiro também o uso de-v
bandeiras do awk para evitar a síndrome do palito de dente inclinado. Então:RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')
RESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "
.bc
faz parte do POSIX, geralmente é pré-instalado.Você pode usar bc pela
-l
opção (a letra L)fonte
-l
no meu sistema, o bc não fará matemática de ponto flutuante.Como alternativa ao bc, você pode usar o awk dentro do seu script.
Por exemplo:
Acima, "% .2f" informa à função printf para retornar um número de ponto flutuante com dois dígitos após a casa decimal. Eu usei eco para canalizar as variáveis como campos, pois o awk opera corretamente nelas. "$ 1" e "$ 2" se referem aos primeiro e segundo campos introduzidos no awk.
E você pode armazenar o resultado como outra variável usando:
fonte
É o momento perfeito para experimentar o zsh, um superconjunto do (quase) bash, com muitos outros recursos interessantes, incluindo matemática de ponto flutuante. Aqui está como o seu exemplo seria no zsh:
Este post pode ajudá-lo: bash - Vale a pena mudar para zsh para uso casual?
fonte
Bem, antes do float era um tempo em que a lógica dos decimais fixos era usada:
A última linha é um bashim, se não estiver usando o bash, tente este código:
A lógica por trás do código é: multiplique por 100 antes de dividir para obter 2 casas decimais.
fonte
Se você encontrou a variante de sua preferência, também pode envolvê-la em uma função.
Aqui estou envolvendo algum basismo em uma função div:
Um forro:
Ou várias linhas:
Agora você tem a função
e use-o como
UPDATE Adicionei um pequeno script que fornece as operações básicas com números de ponto flutuante para o bash:
Uso:
E aqui o script:
fonte
local _d=${3:-2}
é mais simplesNão é realmente um ponto flutuante, mas se você quiser algo que defina mais de um resultado em uma chamada de bc ...
calcula a área e o diâmetro de um círculo cujo raio é dado em $ 1
fonte
Existem cenários nos quais você não pode usar o bc porque ele pode simplesmente não estar presente, como em algumas versões reduzidas do busybox ou sistemas incorporados. Em qualquer caso, limitar sempre as dependências externas é sempre uma boa coisa, portanto, você sempre pode adicionar zeros ao número dividido por (numerador), o mesmo que multiplicar por uma potência de 10 (você deve escolher uma potência de 10 de acordo com a precisão que você precisa), que tornará a divisão um número inteiro. Depois de ter esse número inteiro, trate-o como uma string e posicione o ponto decimal (movendo-o da direita para a esquerda) um número de vezes igual à potência de dez, multiplicado pelo numerador. Essa é uma maneira simples de obter resultados de flutuação usando apenas números inteiros.
fonte
Enquanto você não pode usar a divisão de ponto flutuante no Bash, pode usar a divisão de ponto fixo. Tudo o que você precisa fazer é multiplicar seus números inteiros por uma potência de 10 e depois dividir a parte inteira e usar uma operação de módulo para obter a parte fracionária. Arredondar conforme necessário.
fonte
Eu sei que é velho, mas muito tentador. então, a resposta é: você não pode ... mas você pode. vamos tentar isso:
assim você obtém 2 dígitos após o ponto, truncado (chame-o de arredondamento para baixo, haha) no bash puro (não é necessário iniciar outros processos). é claro, se você precisar apenas de um dígito após o ponto, multiplica por 10 e executa o módulo 10.
o que isso faz:
faixa bônus : a versão bc x 1000 levou 1,8 segundos no meu laptop, enquanto a do bash pura levou 0,016 segundos.
fonte
Como fazer cálculos de ponto flutuante no bash:
Em vez de usar " here strings " (
<<<
) com obc
comando, como um dos exemplos mais votados , aqui está o meubc
exemplo de ponto flutuante favorito , diretamente daEXAMPLES
seção dasbc
páginasman bc
de manual (veja as páginas de manual).Antes de começar, sabemos que uma equação para pi é:
pi = 4*atan(1)
.a()
abaixo está abc
função matemática paraatan()
.É assim que se armazena o resultado de um cálculo de ponto flutuante em uma variável bash - nesse caso, em uma variável chamada
pi
. Observe quescale=10
define o número de dígitos decimais de precisão para 10 nesse caso. Quaisquer dígitos decimais após este local são truncados .Agora, para ter uma única linha de código que também imprime o valor dessa variável, basta adicionar o
echo
comando ao final como um comando de acompanhamento, conforme a seguir. Observe o truncamento com 10 casas decimais, conforme solicitado:Finalmente, vamos jogar alguns arredondamentos. Aqui vamos usar a
printf
função para arredondar para 4 casas decimais. Note que as3.14159...
rodadas agora para3.1416
. Como estamos arredondando, não precisamos mais usarscale=10
para truncar até 10 casas decimais, portanto, apenas removeremos essa parte. Aqui está a solução final:Aqui está outro ótimo aplicativo e demonstração das técnicas acima: medir e imprimir o tempo de execução.
Observe que
dt_min
é arredondado de0.01666666666...
para0.017
:Palavras-chave:
fonte
Use calc. É o exemplo mais fácil que encontrei:
fonte
Para aqueles que tentam calcular porcentagens com a resposta aceita, mas estão perdendo precisão:
Se você executar isso:
Você recebe
99.00
apenas, o que está perdendo precisão.Se você executar desta maneira:
Agora você entende
99.99
.Porque você está dimensionando apenas no momento da impressão.
Consulte aqui
fonte
** Matemática de ponto flutuante seguro para injeção em bash / shell **
Nota: O foco desta resposta é fornecer idéias para uma solução segura para injeção para executar matemática no bash (ou em outras conchas). Obviamente, o mesmo pode ser usado, com pequenos ajustes para executar o processamento avançado de strings, etc.
A maioria das soluções apresentadas apresenta um pequeno scriptlet em tempo real, usando dados externos (variáveis, arquivos, linha de comando, variáveis de ambiente). A entrada externa pode ser usada para injetar código malicioso no mecanismo, muitos deles
Abaixo está uma comparação sobre o uso de vários idiomas para realizar cálculos matemáticos básicos, onde o resultado é em ponto flutuante. Calcula A + B * 0,1 (como ponto flutuante).
Todas as tentativas de solução evitam criar scriptslet dinâmicos, que são extremamente difíceis de manter. Em vez disso, eles usam programa estático e passam parâmetros para a variável designada. Eles manipularão com segurança parâmetros com caracteres especiais - reduzindo a possibilidade de injeção de código. A exceção é 'BC', que não fornece recurso de entrada / saída
A exceção é 'bc', que não fornece nenhuma entrada / saída, todos os dados são fornecidos por programas em stdin e toda saída é enviada para stdout. Todos os cálculos estão sendo executados em uma caixa de proteção, o que não permite efeito colateral (abertura de arquivos etc.). Em teoria, injeção segura por design!
fonte
python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B"
"4200.0" ==> 4205.63aqui está o comando awk: -F = separador de campos == +
fonte