Ir para o conteúdo
Hercles

Operador shl em Pascal

Mensagens Recomendadas

Hercles

Caros, estou com dificuldade para entender este código o número 1 depois do shl faz parte da sintaxe?

procedure TForm1 . rever seOneBi t ( var xnum, hshift : integer ) ;
begin

hshift := ( hshift Shl 1)   or   (xnum and 1 ) ;

xnum := xnum Shr 1 ;

end ;

Editado por Hercles
Formatação corrigida.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
I-NOZex

http://www.delphibasics.co.uk/RTL.asp?Name=Shl

DescriptionThe Shl keyword performs a bitwise shift left of an Integer. The number is shifted Bits to the left.

If Bits is greater than the size of the number type, the Bits value is Mod'ed by the number type size before the shift.

For example;

var

myByte : Byte;

begin

myByte := $2F; // $2F = 47 decimal

myByte := myByte Shl $24;

end;

Gives the same result as Shl 4 = $F0.

espero ajudar ;)

B2R » Beat2Revolution v3.0b | Regista e divulga-nos

beat2revolution.net

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Os SHL e SHR são operadores binários, com funções muito específicas.

Servem para mover à esquerda ou à direita, respectivamente, os bits de um determinado valor.

O seu comportamento é algo imprevisível quando não estamos a lidar com números binários, o que me leva a perguntar:

O que precisas fazer exactamente?


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Flinger

Isto quer dizer, no exemplo ai, que a mudança só vai ocorrer se for menor ou igual a $24?

Não. Quer dizer que a operação só é executada como escrito se o número de bits a rodar for inferior ao tamanho da variável. No caso do exemplo tinha de ser 8.

Também não percebi direito o que é feito com o operador caso este tamanho seja maior...

Editado por Flinger

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Hercles

O código inicial que eu postei, trata-se de um programa que inverte os números binários.... mas não sei se ele só faz a condição de ser maior ou igual....

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Flinger

O código inicial que eu postei, trata-se de um programa que inverte os números binários.... mas não sei se ele só faz a condição de ser maior ou igual....

Olhando para o código com olhos de ver, sim faz sentido. Mas não percebi a tua dúvida acerca da condição. No teu código só rodas um bit de cada vez, logo não tens problemas com isso. O que tens de fazer é chamar esse teu procedimento X vezes, sendo que X é o número de bits da varíavel original (xnum)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Hercles

é confuso este códio...

procedure TForm1 . rever seOneBi t ( var xnum, hshift : integer ) ;   //  Aqui tenho duas variáveis que são do tipo inteiro, que recebe os parametro do programas....
begin

hshift := ( hshift Shl 1) or (xnum and 1 ) ;   // aqui a variável hshift vai receber uma das "situaçãoes" , não entendo.

xnum := xnum Shr 1 ;   // aqui xnum vai receber ele mesmo mas com o shr 1.   não entendo

end ;

Editado por Hercles
Adicionadas tags GeShi

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Flinger

procedure TForm1 . rever seOneBi t ( var xnum, hshift : integer ) ;
begin

hshift := ( hshift Shl 1)   or   (xnum and 1 ) ;

xnum := xnum Shr 1 ;

end ;

hshift é rodado uma vez para a esquerda e recebe o valor do bit mais à direita de xnum,

xnum é rodado para a direita de forma a que o próximo bit seja tratado na próxima chamada.

Um exemplo:

para xnum = 10000010 (130)

e com hshift inicial =0:

primeira chamada

hshift:= 0 or 0 (bit mais à direita de xnum);

xnum = 01000001

2.ª chamada:

hshift = 0 or 1 = 1

xnum = 00100000

3.ª chamada

hshift = 10 (1 shl 1) or 0

xnum = 00010000

e por aí fora até à 8ª chamada em que ficas com

hshift = 01000001

xnum = 00000000

Editado por Flinger

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Hercles

Caramba! show! Estes dois comandos (SHL e SHR) abrem um leque de possibilidades de programação.

Editado por Rui Carlos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Não são comandos, são operadores que são ao mesmo tempo palavras reservadas.

Eu não sou especialista de operações bitwise, mas elas são uma ferramenta poderosíssima. Nestas operações, and, or e xor ganham significados totalmente diferentes, apesar de na sua base estar à mesma os princípios da lógica. Estes são, ao mesmo tempo, operadores binários (operações bitwise) e lógicos (operações booleanas).


Knowledge is free! | Occasional Fortnite player

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
I-NOZex

sem qerer gerar offtopic, mas, qual ai dos gurus de delphi/pascal vai fazer um tutorial na wiki sobre estes operadores?

é que na verdade ha muitos poucos exemplos na web, e ta tudo em ingles... e eu ainda nao entendi totalmente, por isso ficava agradecido ;)


B2R » Beat2Revolution v3.0b | Regista e divulga-nos

beat2revolution.net

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Hercles

Boa ideia I-NOZex. Acho que muitas pessoas vão poder programar melhor quando descobrirem mais possibilidades... Percebi que muitas pessoas desconhecem ou não dão muita importancia a estes operadores e criam algoritmos imensos. :)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Flinger

Não é necessário um tutorial específico para pascal, já que este tipo de operações são comuns a imensas linguagens, só altera os operadores

Como exemplo rápido, shr em C é >> e o shl é <<.

Tendo isto em conta, e para quem quiser saber mais, http://en.wikipedia.org/wiki/Logical_shift_left#Logical_shift

Editado por Flinger

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

Tópico movido e título alterado para algo aceitável. Hercles, mais uma vez vou avisar-te para teres mais cuidado com a escrita, especialmente tratando-se do título de um tópico.

Relativamente à inversão de números binários, porque não fazer isso dentro de um ciclo em vez de termos que executar a funçao x vezes?

const
 BYTEBITS = 8; { nº de bits num byte }

function reverseBits(orig: byte): byte;
var
 i: integer;
 b: byte = 0;
begin
 for i := 0 to SizeOf(orig) * BYTEBITS - 1 do
   b := (b shl 1) or ((orig shr i) and $01);

 reverseBits := b;  { em Delphi é 'result' em vez de 'reverseBits' }
end;

Por alto, esta função vai isolando o último bit de orig e vai "colando" esse bit sempre à direita de b, o nosso resultado temporário. Em cada iteração fazemos shift para a direita de orig para passar ao bit seguinte, e shift para a esquerda de b, para "arranjar espaço" para o bit que "removemos" de orig.

Dada a minha falta de tempo, deixo os pormenores destas operações para quem quiser investigar.

Aqui fica um exemplo no Ideone.

ADENDA:

É importante ter em conta que os efeitos dos operadores shl e shr (e seus equivalentes noutras linguagens) está bem estabelecido e é geralmente concordante quando estamos a falar de números inteiros não-negativos; nos restantes casos pode haver diferenças, e existem particularidades no que diz respeito à forma como se procede ao shifting propriamente dito.

Quando puder publico aqui como se comporta o FreePascal nesse aspecto.

Editado por pwseo

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Hercles

Acho que tem que executar n vezes porque tem uma outra parte do exercícios que eu não postei aqui... Eu acho que é isso! Além da inversão, tem uma animação que vai passando de Tedit em Tedit (aonde vai esta cada número binário) que fica vermelha.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
passarito

Boas,

Vamos lá desmistificar isto.

Não se tem de executar os comandos n vezes, a não ser que se coloque a seguir aos comandos/operadores SHL ou SHR um 1

Se quisermos mover 5 bits para a direita fazemos simplesmente:

01010101 SHR 5

Isto vai dar 00000010

Deixo aqui 2 excelentes explicações. 1 em pdf-PT e outra em video-UK

https://www.youtube.com/embed/_Z3yz0k9dmQ?feature=oembed

http://www.passeidireto.com/arquivo/970424/apost-turbo-pascal/4

Editado por Rui Carlos
  • Voto 1

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
passarito

@Flinger, eu sei que não disseste isso, mas deu-me a ideia aos poucos se estava a dar ideia que apenas dava para deslocar bit a bit, então quiz esclarecer isso e outras dúvidas que pudessem existir através dos 2 links.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

É importante ter em conta que nem tudo é como parece no que diz respeito a estas operações bitwise. Para começar, existem diversas formas de fazer os shifts, sendo as mais conhecidas o shift aritmético e o lógico.

A linguagem Pascal (como implementada no Free Pascal, pelo menos) utiliza shifts lógicos para números inteiros não-negativos e shifts aritméticos para números inteiros negativos.

Em qualquer caso, uma operação de shift implica a perda de um bit (o bit mais significativo (msb) no caso de shl, ou o menos significativo (lsb) no caso de shr); esta perda de um bit é acompanhada da inserçao de um bit 0 no lado oposto, assim:

bits(129)       { = 10000001 }

{ perdemos o msb }
bits(129 shl 1) { = 00000010 }

{ perdemos o lsb }
bits(129 shr 1) { = 01000000 }

Estas características permitem-nos facilmente multiplicar o dividir um número binário por 2 simplesmente com shifts para a esquerda ou direita, respectivamente.

A parte engraçada começa quando metemos números negativos ao barulho. Como sabemos, byte representa uma amplitude de 0..255, e ocupa (como é óbvio), 1 byte. Por sua vez, shortint representa a gama -128..127 e ocupa também 1 byte. Uma vez que os números negativos são representados em complemento de 2, o seu msb indica o sinal do número e é conveniente preservar o msb durante operações de shift de modo a preservar este sinal.

Naturalmente, nestes casos as operações de shift para a direita ficam dependentes do msb para o seu resultado:

bits(5);        { = 00000101 }
msb(5);         { = '0'      }
bits(5 shr 1);  { = 00000010 }
               {   ^- copiado do msb de 5 }

bits(-5);       { = 11111011 }
msb(-5);        { = '1' -- indica-nos que o número é negativo! }
bits(-5 shr 1); { = 11111101 }
               {   ^- copiado do msb de -5 }

Naturalmente, os shifts mais utilizados serão em números inteiros não-negativos (shifts lógicos), especialmente em potências de 2, permitindo assim a fácil previsão do resultado... Ainda assim é sempre bom saber que existem nuances e quais as suas implicações.

Para quem quiser brincar um pouco, aqui ficam as funções bits e msb (basta utilizá-las dentro de um write/writeln):

const
 BYTEBITS = 8;

type
 TBitString = string[bYTEBITS];
 TBit = char;

function bits(n: byte): TBitString;
var
 i: integer;
begin
 bits[0] := char(BYTEBITS);
 for i := 1 to BYTEBITS do
 begin
   if (n and 128) = 128 then
     bits[i] := '1'
   else
     bits[i] := '0';
   n := n shl 1;
 end;
end;

function msb(n: byte): TBit;
begin
 if (n and 128) = 128 then
   msb := '1'
 else
   msb := '0';
end;

Editado por pwseo
  • Voto 2

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.