Mostrando postagens com marcador números binários. Mostrar todas as postagens
Mostrando postagens com marcador números binários. Mostrar todas as postagens

quinta-feira, 9 de agosto de 2012

Jogo das Cartas


Neste jogo, o aluno pode escolher qualquer número e o professor diz facilmente em quais cartas esse número aparece sem olhar para as cartas. Por exemplo, se o aluno escolhe o número 5 então o professor diz que esse número aparece na carta A e C. O contrário também pode ser testado, o aluno diz em quais cartas um certo número aparece e o professor é capaz de descobrir que número é esse. Por exemplo, se o aluno diz que o número desconhecido aparece nas cartas A, B e C, então o professor diz que esse número é o 7. Como o professor realiza essa mágica?






sábado, 18 de fevereiro de 2012

Números inteiros

Entender a representação dos números inteiros no computador é extremamente importante para evitar certos problemas de precisão e que podem fazer uma solução “certa” ficar errada. Saber o que acontece quando ocorre um overflow/underflow e os limites de cada tipo de dados é bastante valioso durante a codificação de uma solução.
Os números inteiros com sinal são armazenados no computador utilizando a notação binária complemento de 2 mais 1. Nesta notação, o bit mais significativo indica o sinal se o dígito for zero então o número é positivo, caso contrário, o número é negativo. No caso do número negativo, a magnitude, ou seja, o valor absoluto do número é obtido fazendo o complemento do número mais 1.

Tabela dos números representados com 3 bit na notação complemento de 2 mais 1
Binário
Complemento
Complemento +1
Decimal
000


0
001


1
010


2
011


3
100
011
100
-4
101
010
011
-3
110
001
010
-2
111
000
001
-1


Problema 1: Maior Inteiro com sinal positivo
O maior inteiro com sinal pode ser obtido fazendo o bit mais significativo igual a 1 e depois fazendo o complemento.
Problema 2: Menor Inteiro com sinal positivo
O menor inteiro com sinal pode ser obtido fazendo o bit mais significativo igual a 1.

#include <stdio.h>
#include <stdlib.h>
int main(){
  char a,b;
  a = (1<<7);
  b = ~(1<<7);
  printf("CHAR      %2d BIT MIN %20d MAX %d\n",sizeof(a)*8,a,b);
  short c,d;
  c = (1<<15);
  d = ~(1<<15);
  printf("SHORT     %2d BIT MIN %20d MAX %d\n",sizeof(c)*8,c,d);
  int e,f;
  e = (1<<31);
  f = ~(1<<31);
  printf("INT       %2d BIT MIN %20d MAX %d\n",sizeof(e)*8,e,f);
  long long int g,h;
  g = (1LL<<63);
  h = ~(1LL<<63);
  printf("LONG LONG %2d BIT MIN %20lld MAX %lld\n",sizeof(g)*8,g,h);
     
}

Saída
CHAR       8 BIT MIN                 -128 MAX 127
SHORT     16 BIT MIN               -32768 MAX 32767
INT       32 BIT MIN          -2147483648 MAX 2147483647
LONG LONG 64 BIT MIN -9223372036854775808 MAX 9223372036854775807


No caso do long long int, para encontrar o maior e o menor número representado, nós utilizamos a constante 1LL e depois deslocamos para a esquerda 63 bit. Se não for utilizada essa constante, o compilador vai dar o seguinte aviso:
 [Warning] left shift count >= width of type

Problema  4: Maior Inteiro sem sinal
O maior inteiro sem sinal pode ser obtido apenas fazendo o complemento de zero, ou seja, colocando todos os bits setados.

#include <stdio.h>
#include <stdlib.h>
int main(){
  unsigned char a;
  a = ~0;
  printf("CHAR      MAX %u\n",a);
  unsigned short b;
  b = ~0;
  printf("SHORT     MAX %u\n",b);
  unsigned int c;
  c = ~0L;
  printf("INT       MAX %u\n",c);
  unsigned long long int d;
  d = ~0LL;
  printf("LONG LONG MAX %llu\n",d);
     
}

Saída

CHAR      MAX 255
SHORT     MAX 65535
INT       MAX 4294967295
LONG LONG MAX 18446744073709551615

Problema 5: Inicializando um vetor inteiro com memset

int B[100];
memset(B,1,sizeof(B));

O código acima não inicializa o vetor B com 1. A função memset() preenche a memória por chars não por ints.

#include <stdio.h>
#include <stdlib.h>
int main(){
    int INF1 = 0x7FFFFFFF; //constante hexadecimal
    // valor = 2147483647   
    //maior valor inteiro da máquina
   
    int INF2 = ~(1<<31);
    // valor = 2147483647
    //maior valor inteiro da máquina usando operações bit-a-bit
   
    int INF3 = INF2/2;
    // valor = 1073741823
    //maior valor inteiro que pode ser multiplicado por 2 sem dar overflow
    //Por exemplo, no algoritmo do floyd-warshall tem o seguinte condicao
    // if( d[i][j] > d[i][k] + d[k][j]) 
    // este comando pode dar overflow por que d[i][k] e d[k][j] são inicializados com INF
    // ou seja, você está somando dois valores INF.
   
    int INF4 = 0x3FFFFFFF;
    // valor 1073741823
    //maior valor inteiro que pode ser multiplicado por 2 sem dar overflow
   
    int INF5 = 0x3F3F3F3F;
  // valor 1061109567
  //maior valor inteiro que pode ser multiplicado por 2 sem dar overflow
  //que pode ser utilizado para inicializar um vetor com memset
  //memset(m,0x3f,sizeof(m));

}




sexta-feira, 10 de fevereiro de 2012

Encontrar o menor entre dois inteiros sem utilizar o operador de comparação

Para descobrir o menor entre dois inteiros sem utilizar a operador de comparação, precisamos saber um pouco
sobre a representação dos números inteirosem notação complemento de dois.

Primeiramente, sabemos que INT_MIN<=x-y<=INT_MAX.
O bit mais significativo (most significant bit) corresponde ao sinal de um número em notação complemento de dois."1"  significa negativo e "0" significa positivo.

A seguinte operação pega o bit mais significativo
#define CHAR_BIT 8 (x-y)>> (sizeof(int)*CHAR_BIT - 1)

A operação sizeof(int) retorna a quantidade de bytes de um inteiro, ou seja, 4 bytes e 8 é a quantidade de bits em cada byte. O operador >> faz o deslocamento para direita. Logo, a operação completa  >> (sizeof(int)*CHAR_BIT - 1) desloca 31 bits para a direita sobrando apenas o bit mais significativo. Se x-y>=0 então x-y>>31 será igual 0. Logo, y será o menor. Se x-y<0 então x-y>>31 será 1. Logo, x será o menor.

#include <stdio.h>
#include <stdlib.h>
#define CHAR_BIT 8

int min(int x,int y){
  if( (x-y)>> (sizeof(int)*CHAR_BIT - 1) ){
    return x;
  }else{
    return y;
  }
}

int main(){
  printf("%d\n",min(28,22));
}