Random

Linguagem de Programação Python

1 Introdução

Aleatoriedade está em nossa volta.Quando lançamos uma moeda ou um dado, nunca temos certeza de qual será o resultado final.A imprevisibilidade tem muitas aplicações como na escolha de vencedores de sorteios ou na geração de casos de teste para experimentos com valores aleatórios com base em algoritmos.

Tendo esse pensamento em mente,a a Python desenvolveu o módulo random. Podemos utilizar esse módulo em jogos para criar inimigos aleatoriamente ou misturar elementos em uma lista.

Como funciona o Random?

Quase todas as funções desse módulo precisam da função random () básica,que gerá um número de ponto flutuante maior ou igual a zero e menor que um.Python usa o gerador de números flutuantes Mersenne Twister. Ele cria números com 53-bit de precisão,com um período de 2**19937-1.É o gerador de número pseudo-aleatório de propósito geral mais usado.

Por vezes, queremos que o gerador de número reproduza a sequência de números criada outra vez.Isso é alcançado ao prover a mesma semente ambas as vezes para o gerador,utilizando a função seed(s,version).

Se o parâmetro s é omitido, o gerador usa o tempo atual do sistema para gerar os números. Veja um exemplo:

import random
 
random.seed(100)
 
random.random() 
# returns 0.1456692551041303
 
random.random()
# returns 0.45492700451402135

Tenha em mente que , diferente de jogas moedas, o módulo gerar números pseudo-aleatórios que são completamente determinísticos,não podem ser usados para criptografia.

2 Gerando Inteiros Aleatórios

Esse módulo tem duas funções para gerar inteiros aleatórios.Podemos criar usando randrange(a) para gerar números inteiros menores que a.

Da mesma forma,podemos usar randrange(a, b [,step~) para gerar um número aleatório dentre range(a,b,step).Um exemplo, random.randrange (0, 100, 3 ) só irá voltar números entre 0 e 100 e que são divisíveis por 3.

Se sabemos tanto os limites inferiores e superiores de números que queremos gerar, podemos utilizar uma função mais simples e intuitiva,randint(a, b). É um simples atalho para randrange(a, b+1).

Funções para Sequências

Para selecionar um elemento aleatório de uma sequência não vazia,podemos usar choice(seq).Com randint(),somos limitados a selecionar números de uma série. choice(seq) que nos da a possibilidade de escolher um número de qualquer sequência quer quisermos.

Outra vantagem dessa função é que não é somente limitada a números.Você pode estar selecionando qualquer elemento aleatoriamente de uma sequência.Por exemplo, o nome do vencedor de um sorteio entre cinco pessoas distintas.providos como cadeias de caracteres,pode ser determinado facilmente usando essa função.

Se misturar a sequência ao invés de selecionar um elemento aleatório, podemos usar a função shuffle(seq).Isso nos resultará em uma mistura da sequência. Para sequência de apenas 10(n) elementos,há um total de 362880 (n!) arranjos diferentes. Com uma sequência maior, o número de permutações possível será maior-implicando que a função nunca poderá gerar todas as permutações de uma sequência grande.

Digamos que temos que escolher 50 estudantes de um grupo de 100 para uma viagem.

Aqui, talvez estejamos tentados a usar choice(seq). O problema é que devemos chamá-la cinquenta vezes no melhor dos cenários, onde não escolhemos o mesmo estudantes de antes.Uma solução melhor é usar sample(seq, k). Ela retornará uma lista de k elementos únicos da sequência em questão. A original será mantida intacta. Os elementos da lista resultante estarão na ordem selecionada. Se k é maior que o número de elemento da sequência, um ValueError será lançado.

Como vemos, shuffle(seq) modifica a lista original, mas sample(seq, k) a mantem intacta.

3 Gerando Pontos Flutuantes Aleatórios

Quando queremos um número entre 0 e 1, podemos usar random().Se quisermos um número em uma série específica, usando uniform(a, b), onde a e b são os limites inferiores e superiores, respectivamente.

Digamos que precisamos gerar um número aleatório entre inferior e superior, de modo que tenha uma maior probabilidade de cair na vizinhança de outro número, moda. Podemos fazê-lo com triangular(inferior, superio, moda). Os valores inferiores e superiores serão 0 e 1 por padrão. De forma similar, o valor padrão da moda será o ponto central entre inferior e superior, resultando numa distribuição simétrica.

Há diversas outras funções para criar números aleatórios com base em distribuições diferentes.Um exemplo,podemos usar Normalvariate(mu, sigma) para gerar um número aleatório com base numa distribuição normal,sendo mu a média e sigma o desvio padrão.

Probabilidade Ponderada

Como vimos anteriormente, é possível gerar números aleatórios com uma distribuição uniforme,triangular ou normal.Mesmo em uma série finita como de 0 a 100, há infinitos números de pontos flutuantes que podemos ser gerados. E se há um número finito de elementos e quremos adicionar mais pesos a alguns valores especificar ao selecionar um número aleatório? Essa situação é comum em sistema de loteria onde números com pouca recompensa são dados maiores pesos.

Se é aceitável na aplicação ter pesoas na forma de inteiros, podemos criar uma lista de elementos cujas frequências dependem de seus pesos. Podemos então usar choice(sea) para selecionar um elemento aleatoriamente dessa lista ponderada. Eis um exemplo mostrando uma seleção do tamanho de prêmio, aleatoriamente.

No nosso caso, levou 10 tentativas para obter uma prêmio de US$2 da lista. As chances de obter o prêmio de US$100 são bem menores. Assim, podemos influenciar outros programas.

Esse módulo pode ser bem útil em várias situações,como misturando questões em um teste ou gerando nomes de usuários ou senhas aleatórias usando shuffle().

Também podemos gerar números aleatórios uniformemente ou dar pesos a números em sua série específica.

4 Estruturas de Repetição

Umas das principais características que consolidaram o sucesso na utilização dos computadores para a resolução de problemas foi a sua capacidade de repetir o processamento de um conjunto de operações para quantidades de dados. Exemplos de conjuntos de tarefas que repetimos várias vezes dentro de uma situação específica que podem ser observados largamente no nosso dia a dia.

As estruturas de repetição provém uma maneira de repetir um conjunto de procedimentos até que determinado objetiva possa ser atingido,quando a repetição se encerra.

Todas as estruturas de repetição têm em comum o fato de haver uma condição de controle, expressa através de uma expressão lógica, que é testada em cada ciclo para determinar se a repetição prossegue ou não.

Um exemplo,consideramos que uma loja de calçados efetue uma venda no crediário para um cliente que ainda não está registrado no seu sistema.Para realizar a venda, é necessário cadastrar o cliente,pedindo informações básicas como:nome,endereço,CPF,RG,etc.Essas etapas para realizar o cadastro seguirão sempre a mesma ordem para cada novo cliente que aparecer na loja. Caso precisássemos desenvolver um sistema para efetuar os cadastros de clientes de uma loja, não haveria lógica que programássemos novamente essas etapas para cada cliente novo, bastaria que desenvolvêssemos uma única vez a seqüência de etapas e que a cada novo cliente usássemos a sequência previamente definida.

As estruturas de repetição são basicamente três: enquanto-faça, faça-enquanto e para-faça. A diferença básica é que enquanto-faça primeiro testa a condição para depois realizar o bloco de comando, ao contrário de faça-enquanto que primeiro executa o bloco para depois realizar o teste. A estrutura para-faça tem embutida um mecanismo de controle para determinar quando o laço deverá ser terminado.

Teste no Início: enquanto-faça.

No algoritmo 15 é mostrado o formato básico da estrutura de repetição enquanto-faca.Antes de adentrar na estrutura de repetição,uma expressão lógica é avaliada e caso o resultado da mesma for verdade,os comandos que estão dentro da estrutura serão executados. Após a execução dos comandos, a expressão lógica é novamente avaliada. Caso o resultado da expressão lógica for falso, o algoritmo sai da estrutura de repetição e segue para a próxima linha.

De uma forma geral, o mecanismo que muda o valor da expressão lógica que controla o laço está contido dentro do bloco de comandos ou depende de alguma variável externa que será fornecida em tempo de execução.

A estrutura enquanto-faça é usada principalmente quando não se sabe com antecedência a quantidade de repetições que precisam ser realizadas. Um exemplo,suponha que estamos oferecemos ao usuários 3 opções de menu sendo que uma dessas opções seria a de sair do programa.

Caso deseje que o usuário possa executar várias vezes as opções dispostas no menu, não temos como adivinhar quando o usuário irá optar por sair do algoritmo, sendo assim, não podemos limitar a repetição à um determinado número de vezes.

Considere um problema mais específico onde necessitamos fazer a leitura de vários nomes de pessoas e a cada nome que é lido devemos escrever na tela a frase "O nome digitado foi nome", onde nome é a variável.A princípio isso deve ser feito inúmeras vezes e quando o usuário digitar um nome igual a “fim” o algoritmo deve parar. Da mesma maneira que no exemplo anterior não podemos definir quando o usuário irá digitar “fim”, e não temos como precisar a quantidade de vezes que o algoritmo deverá repetir esse conjunto de ações.A princípio isso deve ser feito inúmeras vezes e quando o usuário digitar um nome igual a “fim” o algoritmo deve parar. Da mesma maneira que no exemplo anterior não podemos definir quando o usuário irá digitar “fim”, e não temos como precisar a quantidade de vezes que o algoritmo deverá repetir esse conjunto de ações.

Algoritmo

enquanto <expressão lógica> faça
<bloco de comandos>
fim-enquanto

5 Teste no Fim: faça-enquanto

A estrutura faça-enquanto difere da estrutura enquanto-faça somente por executar o bloco de comando antes de testar se a condição é verdadeira, ou seja, o teste da condição é realizado apenas ao final da estrutura. Assim, utilizando o faça-enquanto o bloco de comandos será sempre executado pelo menos uma vez, mesmo que a expressão de controle seja falsa. Seu formato é mostrado no algoritmo 16.

Algoritmo

faça
        <bloco de comandos>
enquanto <expressão lógica>

Repetição com Controle: faça-para

A estrutura para-faça é composta de um mecanismo de controle que estabelece de antemão quantas vezes o laço será executado. A estrutura é mostrada no algoritmo 17 e para ser utilizada precisa das informações referentes aos valores de inicio,fim e incremento. Nessa estrutura, uma determinada variável assumirá valores pertencentes ao intervalo identificado pelos valores de inicio e fim, respeitando o incremento
informado. Por exemplo a expressão i de 0 ate 10 passo 2 significa que i assumirá os valores 0,2,4,6,8,10. Nesse caso, o o laço seria executado 5 vezes.

Algoritmo

para varivel de inicio ate f im passo incremento faça
        <bloco de comandos>
fim-para

Algoritmo

var j: inteiro
para j de 1 ate 100 passo 1 faça
                escreva ("não vou mais fazer bagunça")
fim-para

Contadores e Acumuladores

Em situações em que é necessário realizarmos contagens de ocorrências,ou somatórias e produtórios de valores dentro de um conjunto de dados,devemos utilizar variáveis específicas para fazer o armazenamento dos resultados. Chamamos de contadores para as variáveis que realizam a contagem de ocorrências de um determinado valor (ou situação) e de acumuladores para as variáveis responsáveis por armazenar os resultados de somatórios e produtórios de valores.

Contadores

Os contadores são normalmente inicializados com valor 0 (zero) e incrementados em 1 (um) a cada vez que uma nova ocorrência (ou situação) é observada

Algoritmo

var contador: inteiro
contador ← 0
...
contador ← contador + 1

Por exemplo, considere que dentro de um conjunto de informações referentes a idades e sexos de 50 pessoas, desejemos saber quantas dessas pessoas são do sexo feminino e possuem 18 anos ou mais. Para isso, é necessário inserir um contador para armazenar a quantidade de ocorrências da condição definida no enunciado. Esse contador deve ser inicializado com 0 e incrementado em 1 sempre que o sexo de uma dada pessoa é feminino e sua idade é maior ou igual a 18, como no Algoritmo 20.

Algoritmo

var nome: cadeia
var idade, i, n: inteiro
n ← 0 {a variável n será o contador que armazenará o número de pessoas que pertencem
ao conjunto solicitado no enunciado, ela é inicializada com um valor neutro, nesse caso 0}
para i de 0 ate 50 passo 1 faça
escreva ("digite sexo ('M' ou 'F') e idade da pessoa")
leia(sexo, idade)
se sexo = "M" e idade >= 18 então
n ← n+1 {aumenta em 1 a quantidade de pessoas que pertencem ao conjunto}
fim-se
fim-para
escreva "A quantidade de pessoas do sexo feminino com 18 anos ou mais é :", n

6 Acumuladores

Como comentado anteriormente, os acumuladores são utilizados em dois tipos de situações, para a realização de somatórios e para a realização de produtórios. No caso dos somatórios, o acumulador é normalmente inicializado com o valor 0 e incrementado no valor de um outro termo qualquer, dependendo do problema em questão.

Algoritmo

var acumulador: inteiro
acumulador ← 0
...
acumulador ← acumulador + termo

Pense que no problema anterior,ao invés de desejarmos calcular a quantidade de pessoas que são do sexo feminino e possuem 18 anos, desejemos calcular a soma das idades das pessoas que estão nessa situação. Nesse caso, precisamos inserir no algoritmo um acumulador, que deve ser inicializado em 0, e incrementado no valor da idade da pessoa em questão. Veja no algoritmo abaixo:

Algoritmo

var nome: cadeia
var idade, i, soma: inteiro
soma ← 0 {a variável soma irá armazenar o somatório das idades das pessoas que pertencem ao conjunto solicitado no enunciado, ela é inicializada com um valor neutro, nesse
caso 0}
para i de 0 ate 50 passo 1 faça
escreva ("digite sexo ('M' ou 'F') e idade da pessoa")
leia(sexo, idade)
se sexo = "M" e idade >= 18 então
soma ← soma + idade {aumenta o somatório no valor da idade da pessoa em
questão}
fim-se
fim-para
escreva ("A soma das idades das pessoas do sexo feminino com 18 anos ou mais é :", soma)

Um algoritmo para calcular a média das idades das pessoas do sexo feminino com 18 anos ou mais,pode ser facilmente criado utilizando um contador para armazenar a quantidade de pessoas que pertencem a esse conjunto e um acumulador para armazenar a soma das idades das pessoas.

Em caso de utilizarmos acumuladores para armazenar produtórios é necessário a inicialização do mesmo com o valor neutro da multiplicação (o número 1).A cada iteração o acumulador é então multiplicado por um outro termo qualquer,dependendo do problema em questão.

var acumulador: inteiro
acumulador ← 1
...
acumulador ← acumulador ∗ termo

Um exemplo, para calcular o fatorial de um determinado número, devemos escrever o Algoritmo 24.

var n, i, f at: inteiro
escreva ("digite o número inteiro para calcular o fatorial")
leia(n)
f at ← 1 {a variável fat irá armazenar o fatorial da variável n, ela deve ser inicializada com um valor neutro para a multiplicação, nesse caso 1}
para i de 1 ate n passo 1 faça
f at ← f at ∗ i {a cada iteração o valor do fatorial é acumulado em fat e multiplicado pelo contador i}
fim-para
escreva ("O fatorial de n é igual a ", f at)