Combinação de valores Base 2 é bastante utilizado em "campos" onde precisamos guardar uma combinação de "possibilidades" ou opções em um único campo. Por exemplo em campos de status ou pendencias.
O valor resultante desta combinação único, nenhuma outra combinação resulta no mesmo valor, então com uma lógica simples é possivel achar essa combinação.
Um exemplo disso são os campos Status e Status2 da tabela sys.databases ( http://msdn.microsoft.com/pt-br/library/ms179900.aspx )
Select Name, Status, Status2 from Master.dbo.sysdatabases
Name Status Status2
---------- ----------- -----------
master 65544 1090520064
O Status 65544 é a combinação de 65536 e 8
O Status2 1090520064 é a combinação de 1073741824, 16777216 e 1024
De qualquer forma, a sequencia é sempre número anterior * 2, ou em base-2: 2^n.
2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, etc, etc, etc.....
Seguindo o exemplo de "pendências", para facilitar vamos imagina um caso onde um cliente fez um cadastro em uma loja para contratar um financiamento, e está "devendo" alguns documentos para terminar o processo do financiamento:
Código Valor Descrição
1 2 Falta RG
2 4 Falta CPF
3 8 Falta Certidão de Nascimento
4 16 Falta Certidão de Casamento
5 32 Falta Certidão Negativa
6 64 Falta Comprovante de Renda
7 128 Falta Comprovante de Residencia
8 256 Falta Reservista
9 512 Falta Passaporte
10 1024 Falta Comprovante de Votação
Combinando os valores 3 (8), 5 (32), 7 (128), 8 (256) e 10 (1024) = 1448
Ainda faltam para o cliente:
- Falta Certidão de Nascimento
- Falta Certidão Negativa
- Falta Comprovante de Residencia
- Falta Reservista
- Falta Comprovante de Votação
Uma forma simples de se fazer isso é, sabendo que a soma dos números anteriores nunca é maior ou igual à atual, fazer um loop decrescente "easy cake" diminuindo do resultado final +/- assim:
/************************************************************************************************/
Declare @Numero float, @LimiteSuperior float, @iLimiteSuperior Int
Set @Numero = 1448
Set @LimiteSuperior = 562949953421312 -- 49 opções se precisar mais que isso é só calcular.
Set @iLimiteSuperior = 49
Declare @Resultados table (Base int, Valor float)
While @Numero > 0
Begin
If @LimiteSuperior < = @Numero Begin
Insert Into @Resultados Values (@iLimiteSuperior, @LimiteSuperior)
Set @Numero = @Numero - @LimiteSuperior
End
Set @LimiteSuperior = @LimiteSuperior / 2 --Acha o valor anterior
Set @iLimiteSuperior = @iLimiteSuperior - 1
End
Select * from @Resultados
/************************************************************************************************/
Outra forma, que eu acho mais interessante, tambem é um loop decrescente, porem trabalhamos com Log Base-2 que conseguimos com a divisão: LOG(Numero)/LOG(2).
/************************************************************************************************/
Declare @Numero float, @Expoente float
Declare @Resultados table (Base int, Valor float)
Set @Numero = 1448
While @Numero > 0
Begin
Set @Expoente = FLOOR(LOG(@Numero)/LOG(2))
Insert Into @Resultados Values (@Expoente, POWER(cast(2 as float), @Expoente))
set @Numero = @Numero - POWER(cast(2 as float), @Expoente)
End
Select * from @Resultados
Uma bosta. Só me deixou com mais dúvidas.
ResponderExcluir