A multiplicação dos números de cada linha no arquivo está dando valor negativo

2
#!/bin/bash

sed  's/[^0-9 ]*//g'  $1 | tr " " "\n" > outfile.txt

sed '/^\s*$/d' outfile.txt > outfile1.txt


if [ $2 == "-s" ] || [ $2 == "-si" ] || [ $2 == "-is" ]
then
sum=0;
while read num;
do ((sum += num));
done < outfile1.txt;
echo "SUMA= $sum"
fi

if [ $2 == "-i" ] || [ $2 == "-si" ] || [ $2 == "-is" ]
then
ilo=1;
while read num1;
do((ilo = num1 * ilo));
echo $num1
done < outfile1.txt;
echo "ILOCZYN= $ilo"
fi

este é o meu script e este é o primeiro arquivo de argumento

1 2 3 4 5 4 3 2 3 4 5 4 3 
2 2 2 2 22 3 34 4 4 5 5 5 d 
3 43 54 5 3

isto é o que estou recebendo do script quando eu quero obter uma multiplicação de todos os números e a soma deles

s17545@msh:~$ ./skrypt12.sh logfile.txt -si
SUMA= 241
1
.
. all of the numbers in outfile1.txt 
.
3
ILOCZYN= -2888071394797551616

alguma idéia do que estou fazendo de errado?

    
por Beforeu 02.06.2018 / 00:58

2 respostas

2

Como o página link by @steeldriver explica, estouro aritmético é um fato da vida em Bash. Você poderia, em vez disso:

  • use uma linguagem que suporte números de tamanho arbitrário fora da caixa, como (acredito) Haskell, Lisp ou Scheme,
  • use uma linguagem que lançará uma exceção no estouro aritmético, como Java ou Rust,
  • verificar se o produto diminuiu após cada operação (desde que todos os seus números sejam positivos) ou
  • repensar sua abordagem para que você não precise multiplicar todos os números de uma vez (o que nem sempre é possível).
por 02.06.2018 / 01:43
0

A aritmética da shell é limitada à representação interna inteira.
Bash aritmética em computadores de 64 bits deve ser menor que:

$ echo "$((2**63-1))"
9223372036854775807

Usando a seguinte reescrita do seu script para usar bc e obter o valor correto (removendo o caractere d que parece ser um erro em sua pergunta):

#!/bin/bash

myf="outfile.txt"
sed  's/[^0-9 ]*//g'  "$1" | tr " " "\n" | sed '/^\s*$/d' > "$myf"

sum=$(bc <<< "$(cat "$myf"| tr -s ' \n' '++')0")
ilo=$(bc <<< "$(cat "$myf"| tr -s ' \n' '**')1")

[[ $2 =~ s ]] && echo "SUMA= $sum"
[[ $2 =~ i ]] && echo "ILOCZYN= $ilo"

Recebemos:

$ ./skrypt12.sh logfile.txt -si
SUMA= 241
ILOCZYN= 15558672678912000000

Como você pode ver, o resultado da multiplicação é maior do que o que o bash poderia gerenciar.

    
por 04.06.2018 / 00:19