Bases numéricas em Bash

base_numerica_bash-1_abertura

Algo que só fui me dar conta pois aconteceu de um script em Bash resultar em um erro ao tentar fazer uma simples operação de adição! O motivo? Um simples zero à esquerda do número e que resultou uma certa perda de tempo mas também na “descoberta” que o o Bash sabe tratar outras bases numéricas além da, óbvia, decimal! 🙂

Recriando o problema

Começando com um exemplo bem simples.

$ let valor=10
$ let soma=valor+010
$ echo $soma
18

Ué? O Bash desaprendeu a contar? Um outro exemplo…

$ let valor=10
$ let soma=valor+019
bash: let: 10+019: valor muito grande para esta base de numeração
(token de erro é "019")

Agora piorou! Será algum problema com o uso do let para realizar o cálculo?

$ soma=$(($valor+019))
bash: 10+019: valor muito grande para esta base de numeração
(token de erro é "019")

E agora?

A solução

A explicação é simples, para o Bash valores numéricos iniciados em “0”¹ estão em base numérica octal, ou seja, o “010” acima é na realidade o número 8 em decimal — 1×8+0 = 8 — enquanto que o “019” não constitui um número válido em uma base numérica que somente utiliza algarismos entre zero e sete.

A forma de contornar o “problema” é forçar o Bash a tratar o número como estando em base decimal com o uso do prefixo “10#”.

$ let valor=10
$ let soma=valor+10#010
$ echo $soma
20

E pronto, problema resolvido e aprendida a lição de tratar corretamente os valores numéricos.

(¹) Assim como iniciados em “0x” são considerados em base numérica hexadecimal.

Outras bases numéricas

Usando esta mesma analogia, é possível forçar outras bases numéricas, como o prefixo “2#” para números binários.

$ echo $((2#01101))
13

O prefixo “8#” para números octais.

$ echo $((8#062))
50

O prefixo “16#” para números hexadecimais.

$ echo $((16#041))
65

E até combiná-los na mesma operação…

$ echo $((2#1011+8#62+16#41))
126

Sim, os zeros à esquerda foram mantidos de propósito nos outros exemplos e não são obrigatórios.

Concluindo…

Seguindo esta lógica é possível até mesmo inventar suas próprias bases numéricas por pura curiosidade.

$ echo $((32#giovanni))
569921330930

Ou então para fazer piada com os desavizados! 😀

Anúncios