int binToDec(string bin){
int ret = 0;
int i = 0;
while(bin[i] == '0' || bin[i] == '1'){
if(bin[i] == '0'){
ret <<= 1;
}else{
ret ^= 1;
ret <<= 1;
}
i++;
}
ret >>= 1;
return ret;
}
Alguém consegue me descrever linha a linha o que ocorre dentro do while ali ?!
Simplesmente não consigo entender (eu entendo que ali estão utilizando bitshift, mas o que acontece nesse bitshift ?).
while(bin[i] == '0' || bin[i] == '1'){
if(bin[i] == '0'){
ret <<= 1; // move em uma posição o bit para a esquerda(ex: 00000001 -> 00000010)
}else{
ret ^= 1; // realiza um ou exclusivo com 1(ou seja verdadeiro)
ret <<= 1;
}
i++; // incrementa i em 1 ^_^
}
Eu conheco o sistema de numeração (incluindo qualquer base numerica), mas o que eu não consigo compreender é como utilizar esses operadores de bit pra resolução de algum problema, simplesmente não entra na minha cabeça.
Eu ja li varios posts explicando mas nada me faz entender como utiliza-los…
Logica &:
10011
11101
10001
Logica |:
10011
11101
11111
Mas aqueles especiais: ^, >>, << não os entendo…
Será que alguem ai não tem alguma explicação que me faça entender isso, estou realmente necessitando de entender isso.
Eu conheco o sistema de numeração (incluindo qualquer base numerica), mas o que eu não consigo compreender é como utilizar esses operadores de bit pra resolução de algum problema, simplesmente não entra na minha cabeça.
Eu ja li varios posts explicando mas nada me faz entender como utiliza-los…
Logica &:
10011
11101
10001
Logica |:
10011
11101
11111
Mas aqueles especiais: ^, >>, << não os entendo…
Será que alguem ai não tem alguma explicação que me faça entender isso, estou realmente necessitando de entender isso.
OBRIGADO ![/quote]
Vinícius, isso é uma máscara de bit. Normalmente quem não está no meio da eletrônica não utiliza constantemente. No meu caso eu necessito usar essas máscaras para:
Retirar informações de pacotes enviados por wireless(rádio ou ethernet)
imagine o seguinte pacote de 8 bits enviado por rádio de um controle remoto:
serie do controle número do botão
0010 0001
a informação enviada é 00100001 na variável x
para recuperar o número de série do controle e o botão pressionado no receptor eu faria:
Os números e operadores binários são bem fáceis de entender, mas difíceis de dominar a ponto de efetivamente utiliza-los para resolver problemas.
Eu por exemplo sou capaz de explicar passo-a-passo o que faz esse programa, mas não consigo fazer idéia de seu princípio ou que raciocínio levou à sua criação.
Mas o fato é que funciona! Fiz vários testes aqui e ele converte corretamente uma string binária para o número decimal correspondente.
Vamos ver um caso passo-a-passo:
Aplicando como entrada a string “0101” , correspondente ao numero 5 em decimal.
//Inicializa variavel ret com 0 (00000000 em binário)
//Agora ele vai iterar pelos caracteres da string binária ('0', '1', '0', '1').
//-> Posição 0 = '0'
//Primeira condição do IF: ret <<= 1 (Desloca 1 bit para a esquerda)
ret = ret << 1
ret = 00000000 << 1
ret = 00000000
//-> Posição 1 = '1'
// Segunda condição do IF: ret ^= 1; ret <<= 1; (Faz um XOR com 1 e depois desloca 1 bit para a esquerda)
ret = ret ^ 00000001
ret = 00000000 ^ 00000001
ret = 00000001
ret = ret << 1
ret = 00000001 << 1
ret = 00000010
//-> Posição 2 = '0'
//Primeira condição do IF
ret = ret << 1
ret = 00000010 << 1
ret = 00000100
//-> Posição 3 = '1'
//Segunda condição do IF
ret = ret ^ 00000001
ret = 00000100 ^ 00000001
ret = 00000101
ret = ret << 1
ret = 00000101 << 1
ret = 00001010
//-> Após o loop desloca 1 bit para a direita
// ret >>= 1;
ret = 00001010 >> 1
ret = 00000101
//Retorna ret, que é igual a 00000101, que é igual a 5 - Correto!
Como eu disse, a mecânica da coisa é fácil, mas entender as propriedades dos binários a ponto de criar e compreender tal solução não é tarefa para qualquer um.
Em um sistema de performance crítica, esse tipo de otimização faz toda a diferença.
É como diz aquela piadinha infame… existem 10 tipos de pessoas, as que conhecem binário e as que não
Em um sistema de performance crítica, esse tipo de otimização faz toda a diferença.
É como diz aquela piadinha infame… existem 10 tipos de pessoas, as que conhecem binário e as que não :-)[/quote]
igual o codigo inicial q poderia ser assim:
int binToDec(string bin){
int ret = 0;
int i = 0;
while(bin[i] == '0' || bin[i] == '1'){
ret <<= 1;
if (bin[i] == '1') ret++;
i++;
}
return ret;
}
ou
int binToDec(string bin){
int ret = 0;
int i = 0;
while(bin[i] == '0' || bin[i] == '1'){
ret *= 2;
if (bin[i] == '1') ret++;
i++;
}
return ret;
}
Compartilhando um caso aqui também, tenho um algoritmo que converte um byte array GUID de um sistema externo para o padrão do Java, que é UUID:
public static UUID toUUID(byte[] byteArray) {
long msb = 0;
long lsb = 0;
for (int i = 0; i < 8; i++) {
msb = (msb << 8) | (byteArray[i] & 0xff);
}
for (int i = 8; i < 16; i++) {
lsb = (lsb << 8) | (byteArray[i] & 0xff);
}
return new UUID(msb, lsb);
}
isto não é suficiente, pois se for fazer o uuid.toString() não bate com a string original do GUID. Rachei de procurar e acabei encontrando um algoritmo que faz um shift maluco, devido ao padrão do bit converter no Java ser little-endian. Enfim, dado que tenho o uuid na mão, o algoritmo continua assim:
// Gero o byte array do UUID.
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
byte[] originalBytes = new byte[16];
for (int i = 0; i < 8; i++) {
originalBytes[i] = (byte) (msb >> 8 * (7 - i));
}
for (int i = 8; i < 16; i++) {
originalBytes[i] = (byte) (lsb >> 8 * (7 - i));
}
// Faço o shift maluco para chegar no padrão GUID
byte[] reversedBytes = new byte[16];
// Troco os 4 primeiros de posição
reversedBytes[0] = originalBytes[3];
reversedBytes[1] = originalBytes[2];
reversedBytes[2] = originalBytes[1];
reversedBytes[3] = originalBytes[0];
// Troco o quinto com sexto
reversedBytes[4] = originalBytes[5];
reversedBytes[5] = originalBytes[4];
// Troco o sétimo com o oitavo
reversedBytes[6] = originalBytes[7];
reversedBytes[7] = originalBytes[6];
// Mantém o restante
System.arraycopy(originalBytes, 8, reversedBytes, 8, 16 - 8);