paulo1205
(usa Ubuntu)
Enviado em 22/02/2016 - 10:07h
filipee6 escreveu:
for num in {$1..$2} do
Para fazer a soma, você só tem de fazer isto:
((soma=0))
for num in {$1..$2}; do ((soma+=num)); done
ENTRETANTO:
A construção “{a..b}” coloca todas as parcelas como texto em memória RAM. Então, se o usuário pedir para somar os valores entre um e cem milhões, por exemplo, você vai alocar uma absurdidade de memória, com grandes chances de provocar um severo
thrashing e, na prática, congelar a máquina.
Uma alternativa é fazer um loop que não expanda previamente todos os possíveis valores. Por exemplo:
((soma=0))
for ((num=$1; num<=$2; num++)); do ((soma+=num)); done
Com isso, o consumo de memória fica baixo (suficiente para acomodar apenas as variáveis
soma e
num), e a máquina não vai congelar.
O problema é que essa operação é lenta, e isso fica especialmente evidente quando o número de parcelas aumenta (na minha máquina, um Core i5 de 3.2GHz, levou 7min52s para somar de um a cem milhões). E lenta é também a sugestão dada de gerar uma tripa de texto com
seq e passá-la para
bc efetuar a conta.
Muito melhor é você usar o mínimo de conhecimento matemático, e usar a forma reduzida de somar os termos de uma progressão aritmética,
soma(a(n)..a(m)):=(a(n)+a(m))*(m+1-n)/2.
No seu caso particular,
a(k)=k, de modo que sua soma se calcula com a seguinte simples expressão.
((soma=($1+$2)*($2+1-$1)/2))
Caso o shell não tenha precisão suficiente para representar alguma das parcelas ou a soma final, você pode usar o
bc.
soma=`echo "($1+$2)*($2+1-$1)/2" | bc`