[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [shell-script] Calculo em Centesimos
From: |
Arkanon |
Subject: |
Re: [shell-script] Calculo em Centesimos |
Date: |
Fri, 9 Dec 2011 00:17:59 -0200 |
Em 8 de dezembro de 2011 13:12, williamalves1975br escreveu:
> Alguém conhece uma forma simples, se é que existe, para realizar o calculo
> da diferença entre os tempos abaixo?
>
> 14:59:53,391 14:59:53,419
> 14:59:54,845 14:59:55,866
> 14:59:55,902 15:01:56,918
>
> O Resultado deveria ter o mesmo formato.
>
> Nesse momento estou realizando a conversão para centesimos e depois vou
> precisar converter novamente.
>
Oi.
Ficou meio extensa a resposta, mas a ideia em si é curta :-p
É uma abordagem mais matemática desse assunto.
O formato "*d H:M:S.m*" (dia, hora, minuto, segundo e milésimo) pode ser
encarado como um número deveras complicado :-p Ele é escrito
simultaneamente em 3 bases numéricas: dia e milésimo na base decimal, hora
na base 24 e minuto e segundo na sexagesimal (60).
Não vamos pensar no dia e no milésimo, num primeiro momento. E vamos
assumir que não teremos uma quantidade de horas que ultrapasse 60.
Então o número H:M:S é um número na base sexagesimal com 3 dígitos. Ao
invés de pensar em símbolos para dígitos com valor decimal superior a 9,
pensemos em seu próprio valor decimal.
Assim, 12:37:30 é composto pelos dígitos 12, 37 e 30. Literalmente.
Convertemos o número acima para a base decimal como convertemos qualquer
número em qualquer base para a decimal. Nesse caso, a base 60:
12:37:30[60] = 12*60*60 + 37*60 + 30 = 45450[10]
Aí, se queremos a diferença entre 2 números sexagesimais, fazemos o que
todo mundo faz. Convertemos para segundos (decimal), subtraímos e,
eventualmente, reconvertemos para a base sexagesimal.
Então, para que serve tudo isso que eu disse?
Para, uma vez encarando dessa forma as "strings" de hora, minuto e segundo,
usarmos as ferramentas de manipulação de bases numéricas nativas do bash e
presentes no bc para simplificar o trabalho.
No bash podemos trabalhar de forma transparente com uma vasta gama de bases
numéricas. Basta usar o número numa determinada base na forma *
b#numeronabase*. Ele assume os dígitos *0..9* para bases até a decimal e *
a..zA..Z* para bases superiores (até 64).
Então, o primeiro passo é definir a sequência de dígitos:
*C=({0..9} {a..z} {A..Z})*
Depois, lemos as duas strings de hora (*$1 e $2*), passando-as para arrays
após definir o ":" como separador de campo:
*IFS=: H1=($1) H2=($2)
*
Montamos os números sexagesimais, pegando os dígitos correspondentes em $C:
*for d in ${H1[*]}; do S1=$S1${C[$d]}; done
for d in ${H2[*]}; do S2=$S2${C[$d]}; done*
Pode muito bem haver uma forma melhor de fazer essa junção, sem usar loops.
Não me preocupei com isso agora.
Convertemos os números sexagesimais para decimal:
*D1=$[60#$S1]
D2=$[60#$S2]*
E, usando o bc, passamos a diferença entre eles de decimal para sexagesimal:
*bc <<< "obase=60;$D2-$D1"*
Como o bc não representa bases numéricas superiores a 16 com dígitos
especiais, mas os mantém com seu valor decimal, teremos o resultado já no
formato "*H M S*", precisando apenas trocar o espaço entre eles por ":"
Ex:
*12:37:30 -> cBu -> 45450
14:54:33 -> eSx -> 53673
53673 - 45450 = 8223 -> 02 17 03
*
É isso.
O método acima não resolve todo o problema, mas talvez ajude de alguma
forma.
[]'s numéricos
--
(o_ @arkanon <http://twitter.com/arkanon> (Twitter) __o
//\ address@hidden _`\<,
V_/_ www.lsd.org.br (_)/(_)
---------------------------------
[As partes desta mensagem que não continham texto foram removidas]