Um exemplo rápido do que eu quero usar o script bash:
#!/bin/bash
echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
echo "scale=2; $float/1.18" |bc -l
read -p "Press any key to continue..."
bash scriptname.sh
Supondo que o preço seja: 48,86 A resposta será: 41.406779661 (41.40 na verdade porque estou usando scale=2;
)
Minha pergunta é: Como arredondar o segundo decimal para mostrar a resposta dessa maneira ?: 41.41
bc
não consiga alcançar o que está sendo solicitado (ou pelo menos a pergunta que eu estava fazendo quando encontrei este post), que é como arredondar decimais usandobc
(que é chamado porbash
).r()
função, para que você possa usá-lobc -le "r($float/1.18, 2)"
.Respostas:
Uma função bash round:
Usado no seu exemplo de código:
Boa sorte: o)
fonte
-0.5
$2 = 3
eu tinha que usarecho $(env printf %.3f $(echo "scale=3;((1000*$1)+0.5)/1000" | bc))
. Cuidado com o env antes do printf! Isso vai te ensinar novamente que é sempre importante entender o que você está copiando e colando de outro lugar.if [
eco "$ 1/1" | bc` -gt 0] `- existe uma maneira mais elegante de verificar (exceto analisar a string para" - ")?Solução mais simples:
fonte
+0.5
. Tenteprintf "%.2f\n" "$(bc -l <<<"48.86/1.18")" "$(bc -l <<<"-48.86/1.18")"
e você receberá41.41
e-41.41
.echo "$float/1.18" | bc -l | xargs printf %.2f
bash: printf: 1.69491525423728813559: invalid number
dependendo da localidade.Arredondamento de bash / awk:
Se você tem python, pode usar algo como isto:
fonte
echo "$float" |awk '{printf "%.2f", $1/1.18}'
executará a matemática solicitada da pergunta na percisão solicitada de centésimos. Isso é tanto "usando o bash" quanto abc
chamada da pergunta.python -c "print(round($num))"
ondenum=4.678923
. Não há necessidade de mexer com stdin. Você pode também rodada de n dígitos assim:python -c "print(round($num, $n))"
.echo 5 | python -c "print int(round((float(raw_input())/2)-0.5))"
(Quando + será arredondado para cima e para baixo).Aqui está uma solução puramente bc. Regras de arredondamento: em +/- 0,5, arredondar para zero.
Coloque a escala que você está procurando em $ result_scale; sua matemática deve estar onde $ MATH está localizado na lista de comandos bc:
fonte
MATH=-0.34;result_scale=1;bc <<MATH
, #ObjectiveAndClear: 5, como explicado aqui :) #Eu sei que é uma pergunta antiga, mas tenho uma solução 'bc' pura sem 'if' ou ramificações:
Use-o como
bcr '2/3' 5
oubcr '0.666666' 2
-> (expressão seguida de escala)Isso é possível porque em bc (como C / C ++) é permitido misturar expressões lógicas em seus cálculos. A expressão
((t>0)-(t<0))/2)
será avaliada em +/- 0,5, dependendo do sinal de 't' e, portanto, usará o valor correto para arredondar.fonte
bcr "5 / 2" 0
retorna em2
vez de3
. Estou esquecendo de algo?Na verdade, é simples: não há necessidade de adicionar explicitamente uma variante "-0.5" codificada para números negativos. Falado matematicamente, apenas calcularemos o valor absoluto do argumento e ainda adicionaremos 0,5 como normalmente. Mas como (infelizmente) não temos nenhuma
abs()
função interna à nossa disposição (a menos que codifiquemos uma), simplesmente negaremos o argumento, se for negativo.Além disso, provou ser muito complicado trabalhar com o quociente como parâmetro (já que, para minha solução, preciso acessar o dividendo e o divisor separadamente). É por isso que meu script tem um terceiro parâmetro adicional.
fonte
echo .. |
aritmética de shell, qual é o objetivoecho $()
? É fácil de explicar: suas strings here sempre exigirão um diretório gravável/tmp
! E a minha solução também irá trabalhar em um ambiente somente de leitura, por exemplo, um shell de root de emergência, onde/
é não sempre gravável por padrão. Portanto, havia uma boa razão pela qual eu codifiquei dessa maneira.echo $()
necessário? Isso e indentação levaram minhas edições, as herestrings simplesmente aconteceram.echo $()
disso estava atrasado para ser consertado era, de fato, a penúltima linha, lol. Obrigado pelo aviso. Pelo menos este parece muito melhor agora, não posso negar. Enfim, adorei a lógica disso. Muitas coisas booleanas, menos "se" s supérfluas (o que certamente aumentaria o código em 50%).Ainda estou procurando uma
bc
resposta pura para arredondar apenas um valor dentro de uma função, mas aqui está umabash
resposta pura :Basicamente, isso extrai cuidadosamente os decimais, multiplica tudo por 100 bilhões (10¹⁰,
10**10
polbash
), ajusta a precisão e o arredondamento, executa a divisão real, divide de volta à magnitude apropriada e reinsere o decimal.Passo a passo:
A
embiggen()
função atribui a forma inteira truncada de seu argumento$int
e salva os números após o ponto$fraction
. O número de dígitos fracionários é anotado em$precision
. A matemática multiplica 10¹⁰ pela concatenação de$int
e$fraction
ajusta-a para corresponder à precisão (por exemplo,embiggen 48.86
torna-se 10 ×488600000000
4886/100 e retorna 488.600.000.000).Como queremos uma precisão final de centésimos, multiplicamos o primeiro número por 100, adicionamos 5 para fins de arredondamento e dividimos o segundo número. Essa tarefa
$answer
nos deixa cem vezes a resposta final.Agora precisamos adicionar o ponto decimal. Atribuímos um novo
$int
valor para$answer
excluir seus dois dígitos finais, depoisecho
com um ponto e$answer
excluindo o$int
valor que já foi resolvido. (Não importa o erro de destaque da sintaxe que faz com que isso pareça um comentário)(Bashism: exponenciação não é POSIX, então isso é um basismo. Uma solução POSIX pura exigiria que loops adicionassem zeros em vez de usar potências de dez. Além disso, "embiggen" é uma palavra perfeitamente cromulante.)
Um dos principais motivos pelos quais uso
zsh
como shell é o suporte à matemática de ponto flutuante. A solução para esta pergunta é bastante direta emzsh
:(Adoraria ver alguém adicionar um comentário a esta resposta com o truque para ativar a aritmética de ponto flutuante
bash
, mas tenho certeza de que esse recurso ainda não existe.)fonte
se você tiver o resultado, por exemplo, considere 2.3747888
Tudo que você tem a fazer é:
isso arredonda o número corretamente exemplo:
os decimais são removidos
bc
e, por isso, arredondam para 2, como deveriafonte
Eu tive que calcular a duração total de uma coleção de arquivos de áudio.
Então eu tive que:
A. obtenha a duração de cada arquivo ( não mostrado )
B. some todas as durações (elas estavam em
NNN.NNNNNN
(fp) segundos)C. separar horas, minutos, segundos, subsegundos.
D. produz uma string de HR: MIN: SEC: FRAMES, em que frame = 1/75 seg.
(Os quadros vêm do código SMPTE usado nos estúdios.)
R: use
ffprobe
e analise a linha de duração em um número fp (não mostrado)B:
C:
D:
fonte
Aqui está uma versão abreviada do seu script, corrigida para fornecer a saída desejada:
Observe que arredondar para o número inteiro mais próximo equivale a adicionar 0,5 e pegar o piso ou arredondar para baixo (para números positivos).
Além disso, o fator de escala é aplicado no momento da operação; então (estes são
bc
comandos, você pode colá-los no seu terminal):fonte
Implementação bc pura conforme solicitado
define ceil(x) { auto os,xx;x=-x;os=scale;scale=0 xx=x/1;if(xx>x).=xx-- scale=os;return(-xx) }
se você colocar isso em um arquivo chamado functions.bc, poderá arredondar para
echo 'ceil(3.1415)' | bc functions.bc
Código para a implementação bc encontrado em http://phodd.net/gnu-bc/code/funcs.bc
fonte
fonte
Você pode usar o awk, sem necessidade de pipes:
Defina o preço antecipadamente com a variável de ambiente
PRICE=<val>
.Em seguida, chame o awk -
$PRICE
entrará no awk como uma variável do awkprice
.Em seguida, é arredondado para o centésimo mais próximo com +,005.
A opção de formatação printf
%.2f
limita a escala a duas casas decimais.Se você precisar fazer isso muito desta maneira, será muito mais eficiente que a resposta selecionada:
fonte