Tutoriais e Programação
AoA - Cap.2 - Funções booleanas genéricas
- Detalhes
-
Categoria: Art of Assembly
-
Atualização: Domingo, 19 Abril 2009 20:26
-
Autor: vovó Vicki
-
Acessos: 8484
Para uma aplicação específica pode-se criar uma função lógica que dê um determinado resultado. Suponha, entretanto, que você queira escrever um programa para simular qualquer função booleana possível.
Por exemplo, imagine um programa que permita a entrada de uma função booleana arbitrária com quatro variáveis diferentes. Este programa lerá as entradas e produzirá necessariamente os resultados das funções. Uma vez que o número de funções de quatro variáveis únicas é grande (65536, para ser exato), não é prático incluir uma solução específica para cada uma no programa. O que se precisa é de uma função lógica genérica, uma que calcule os resultados para qualquer função arbitrária. Esta seção descreve como escrever tal função.
Uma função booleana genérica de quatro variáveis requer cinco parâmetros - os quatro parâmetros de entrada e um quinto parâmetro que especifica a função que deve ser calculada. Apesar de haver muitas formas de se especificar uma função, optamos por passar o número da função booleana como quinto parâmetro.
À primeira vista você poderia perguntar como é possível calcular uma função utilizando o seu número. Contudo, lembre-se de que os bits que formam o número da função vêm diretamente da tabela verdade da própria função. Então, se extrairmos os bits do número da função, poderemos construir a tabela verdade para a mesma. Além disto, se selecionarmos somente o iésimo bit do número da função, onde i = D*8 + C*4 + B*2 + A, obteremos o resultado da função para os valores especificados para A, B, C e D. O exemplo a seguir, em C e Pascal, mostra como escrever tais funções:
/************************************************************************/
/* */
/* Este programa C demonstra como escrever uma função booleana genérica */
/* que pode calcular qualquer função lógica de quatro variáveis. Com os */
/* operadores de manipulação de bits e com a E/S hexadecimal, esta é */
/* uma tarefa fácil de ser efetuada com a linguagem C. */
/* */
/************************************************************************/
#include
#include
/* função lógica genérica. O parâmetro "Func" contém o número 16 */
/* da função lógica. Na verdade, isto é a função lógica de uma tabela */
/* verdade codificada. Os parâmetros a, b, c e d são as entradas para */
/* a função lógica. Se tratarmos "func" como um array 2x2x2x2 de bits, */
/* esta função particular seleciona o bit "func[d,c,b,a]" da função. */
int generic(int func, int a, int b, int c, int d)
{
/* Retorna o bit especificado por a, b, c e d */
return (func >> (a + b*2 + c*4 + d*8)) & 1;
}
/* Programa principal para comandar a função lógica genérica escrita em C. */
main()
{
int func, a, b, c, d;
/* Repete o seguinte até o usuário entrar zero. */
do
{
/* Obtém o número da função (tabela verdade) */
printf("Entre o valor da função (hex): ");
scanf("%x", &func);
/* Se o usuário especificar zero como nro da função */
if (func != 0)
{
printf("Entre os valores para d, c, b & a: ");
scanf("%d%d%d%d",
&d, &c, &b, &a);
printf("O resultado é %d\n", generic(func,a,b,c,d));
printf("Func = %x, A=%d, B=%d, C=%d, D=%d\n",
func, a, b, c, d);
}
} while (func !=0);
}
O programa a seguir, em Pascal, foi escrito para Standard Pascal. O Standard Pascal não fornece quaisquer operações para manipulação de bits, então este programa ficou grande porque ele precisa manipular os bits utilizando um array de inteiros. Muitos Pascals modernos (especialmente o Turbo Pascal) fornecem operações de bits embutidas ou rotinas em bibliotecas que operam bits. Este programa seria muito mais fácil de escrever utilizando tais características não padronizadas.
program GenericFunc(input,output);
(* Já que o Pascal Padrão não fornece uma forma fácil para manipular *)
(* diretamente bits em um inteiro, simularemos o número da função *)
(* utilizando um array de 16 inteiros. "GFTYPE" é o tipo desse array. *)
type
gftype = array [0..15] of integer;
var
a, b, c, d:integer;
fresult:integer;
func: gftype;
(* Pascal Padrão não tem a capacidade de deslocar um dado inteiro para *)
(* a esquerda ou a direita. Então, simularemos um valor de 16 bits *)
(* utilizando um array de 16 inteiros. Podemos simular o deslocamento *)
(* movendo o dado através do array. *)
(* *)
(* Note que o Turbo Pascal *fornece* os operadores shl e shr. *)
(* Contudo, este código é escrito para funcionar com o Pascal Padrão, *)
(* e não apenas em Turbo Pascal. *)
(* *)
(* ShiftLeft desloca os valores em func para a esquerda e insere o *)
(* valor deslocado no bit de posição zero *)
procedure ShiftLeft(shiftin:integer);
var i:integer;
begin
for i := 15 downto 1 do func[i] := func[i-1];
func[0] := shiftin;
end;
(* ShiftNibble desloca o dado em func para a esquerda quatro posições e *)
(* insere os quatro bits a , b, c & d nas posições vagas *)
procedure ShiftNibble(d,c,b,a:integer);
begin
ShiftLeft(d);
ShiftLeft(c);
ShiftLeft(b);
ShiftLeft(a);
end;
(* ShiftRight desloca o dado em func uma posição à direita. Desloca *)
(* um zero para dentro do bit de mais alta ordem do array. *)
procedure ShiftRight;
var i:integer;
begin
for i := 0 to 14 do func[i] := func[i+1];
func[15] := 0;
end;
(* ToUpper converte um caracter minúsculo para maiúsculo. *)
procedure toupper(var ch:char);
begin
if (ch in ['a'..'z']) then ch := chr(ord(ch) - 32);
end;
(* ReadFunc lê um número de função hexadecimal fornecido pelo usuário *)
(* e põe este valor no array func (bit a bit) *)
function ReadFunc:integer;
var ch:char;
i, val:integer;
begin
write('Entre o número da função (hexadecimal): ');
for i := 0 to 15 do func[i] := 0;
repeat
read(ch);
if not eoln then begin
toupper(ch);
case ch of
'0': ShiftNibble(0,0,0,0);
'1': ShiftNibble(0,0,0,1);
'2': ShiftNibble(0,0,1,0);
'3': ShiftNibble(0,0,1,1);
'4': ShiftNibble(0,1,0,0);
'5': ShiftNibble(0,1,0,1);
'6': ShiftNibble(0,1,1,0);
'7': ShiftNibble(0,1,1,1);
'8': ShiftNibble(1,0,0,0);
'9': ShiftNibble(1,0,0,1);
'A': ShiftNibble(1,0,1,0);
'B': ShiftNibble(1,0,1,1);
'C': ShiftNibble(1,1,0,0);
'D': ShiftNibble(1,1,0,1);
'E': ShiftNibble(1,1,1,0);
'F': ShiftNibble(1,1,1,1);
else write(chr(7),chr(8));
end;
end;
until eoln;
val := 0;
for i := 0 to 15 do val := val + func[i];
ReadFunc := val;
end;
(* Generic - Calcula a função lógica genérica especificada pelo *)
(* número da função "func" nas quatro variáveis *)
(* a, b, c & d. Faz isto retornando o bit *)
(* d*8 + c*4 + b*2 + a da função. *)
function Generic(var func:gftype; a,b,c,d:integer):integer;
begin
Generic := func[a + b*2 + c*4 + d*8];
end;
begin (* main *)
repeat
fresult := ReadFunc;
if (fresult <> 0) then begin
write('Entre os valores para D, C, B, & A (0/1):');
readln(d, c, b, a);
writeln('O resultado é ',Generic(func,a,b,c,d));
end;
until fresult = 0;
end.
O código a seguir demonstra o poder das operações de manipulação de bits. Esta nova versão do código acima utiliza características especiais presentes na linguagem de programação do Turbo Pascal que permitem deslocar bits para a direita ou para a esquerda e fazer um AND lógico bit a bit em variáveis inteiras:
program GenericFunc(input,output);
const
hex = ['a'..'f', 'A'..'F'];
decimal = ['0'..'9'];
var
a, b, c, d:integer;
fresult:integer;
func: integer;
(* Aqui está uma segunda versão da função genérica do Pascal que *)
(* utiliza as características do Turbo Pascal para simplificar o *)
(* programa. *)
function ReadFunc:integer;
var ch:char;
i, val:integer;
begin
write('Entre o número da função (hexadecimal): ');
repeat
read(ch);
func := 0;
if not eoln then begin
if (ch in Hex) then
func := (func shl 4) + (ord(ch) and 15) + 9
else if (ch in Decimal) then
func := (func shl 4) + (ord(ch) and 15)
else write(chr(7));
end;
until eoln;
ReadFunc := func;
end;
(* Generic - Calcula a função lógica genérica especificada pelo *)
(* número da função "func" nas quatro variáveis *)
(* a, b, c e d. Faz isto retornando o bit *)
(* d*8 + c*4 + b*2 + a de func. Esta versão deixa o *)
(* trabalho para o operador de deslocamento do Turbo *)
(* Pascal e sua habilidade para fazer operações em *)
(* bits de inteiros. *)
function Generic(func,a,b,c,d:integer):integer;
begin
Generic := (func shr (a + b*2 + c*4 + d*8)) and 1;
end;
begin (* main *)
repeat
fresult := ReadFunc;
if (fresult <> 0) then begin
write('Entre os valores para D, C, B, & A (0/1):');
readln(d, c, b, a);
writeln('O resultado é ',Generic(func,a,b,c,d));
end;
until fresult = 0;
end.
Fonte
mfx broker инвестициичто сделать чтобы не пригорала чугунная сковородалобановский класс харьковасус планшеталександр лобановскийлобановский александр досьехарьков никас