Introdução à programação e aos algoritmos

João Araujo Ribeiro · Capítulo 32 de 103

Páginas do PDF

Introdução à programação e aos algoritmos

2.7.4 Dados Não Numéricos

Você já está acostumado com imprecisões dos números reais decimais. A fração 1/3 não tem uma

representação exata na base dez. Pode ser 0,3, 0,33 ou 0,333. Não importa quantas casas decimais você use, nunca será igual a 1/3.

É um fato matemático. Algumas frações não podem ser representadas de maneira exata como

números de ponto flutuante. Toda base numérica, seja decimal ou binária, terá essa característica. A confusão aparece porque as frações das duas bases não são as mesmas. Assim, na base 10 a imprecisão aparece com 1/3, mas não com 1/10.

A solução de usar aritmética com números inteiros, multiplicando os números por potências de 10

até eliminar todas as casas decimais, nem sempre é uma boa ideia. Você teria que fazer modificações nos seus algoritmos e nesse processo poderia inserir erros. Além disso, nem toda linguagem de programação trabalha com inteiros ilimitados, como Python. Os resultados também teriam de ser vigiados para se adequarem a essa aritmética exclusiva de inteiros.

O que quero que você entenda é que devemos usar números reais de ponto flutuante com cuidado.

A precisão de computadores nos cálculos é uma disciplina à parte, na qual são analisadas técnicas para trabalhar da maneira mais eficiente e corretamente possível com as limitações do computador quanto aos cálculos numéricos. Não está no escopo deste livro apresentar essas técnicas, mas se a precisão de cálculos matemáticos é essencial a seus programas, você terá de estudá-las.

Dica 2.12 – Python tem números imaginários.

Python é uma das poucas linguagens de programação que fornece números imaginários diretamente como um tipo básico da

linguagem. Um número imaginário i é de nido como a raiz quadrada de –1 (i2 = -1 ⇒ i = ).

Para de nir um número imaginário em Python, basta terminar um número literal qualquer com a letra j ou J:

x = 5j

Para criar um número complexo, basta escrever sua parte real acompanhada de sua parte imaginária, com j:

x = 1 + 5j

 

EXERCÍCIO 2.14

Vamos supor que podemos dobrar uma folha de papel quantas vezes quisermos. Essa folha tem espessura de 0,1 mm. Depois de

a dobrarmos 107 vezes, qual seria sua altura? Lembre-se de que a cada dobradura, a espessura dobra. Crie um programa que

execute e imprima este cálculo.

 

EXERCÍCIO 2.15

Faça um programa que dê o resultado do exercício anterior em metros, quilômetros e anos-luz.

 

2.7.4 DADOS NÃO NUMÉRICOS

Os primeiros computadores eram máquinas devoradoras de números. Mas logo se percebeu que poderiam ir além do processamento numérico.

Um aspecto essencial para o desenvolvimento de algoritmos é a tomada de decisões. Não basta

apenas calcular, o computador deve também fazer escolhas, e para tanto precisa processar entidades lógicas bem simples, que possam expressar os conceitos de verdadeiro e falso. Nas linguagens de programação esses conceitos vão ser referenciados pelas palavras em inglês: True e False, ou pelos valores 1 e 0, respectivamente.

Valores lógicos surgem de operações lógicas. Também chamamos esses valores de booleanos, em

homenagem ao matemático do século XIX George Boole. Uma das operações mais comuns é o teste de igualdade. Frequentemente vamos testar se duas variáveis têm o mesmo valor e, de acordo com o resultado, tomar alguma decisão que irá alterar o fluxo de execução de nosso algoritmo. Se quisermos saber se a variável x é igual à variável y e executar alguma ação de acordo com o resultado, em um algoritmo podemos escrever:

se x é igual a y:

execute comando

ou podemos usar o símbolo de igual:

se x = y:

execute comando

mas aqui surge um problema. Muitas linguagens de programação usam o símbolo de igual para a atribuição. Se você usar o mesmo símbolo para o teste de igualdade, vai acabar cometendo o erro de fazer uma atribuição em vez de testar duas variáveis. Com a finalidade de evitar essa confusão, muitas linguagens usam o sinal de igual duplo (==). Em Python, ficaria:

if x == y:

Voltarei a falar sobre testes e lógica booleana nos próximos capítulos, quando estudarmos tomada

de decisões. Por enquanto, é suficiente entender que essas estruturas permitem um desvio no fluxo normal de execução de um algoritmo.

 

George Boole (1815-1864)

George Boole foi um matemático inglês do século XIX, criador dos fundamentos da hoje chamada Álgebra Booleana. Em seu trabalho, introduziu o uso de símbolos para processar entidades lógicas. Estas entidades só podem assumir os valores 0 (falso) e 1 (verdadeiro). As funções básicas da Álgebra Booleana são E, OU e complemento. Se A e B são proposições, a expressão lógica A ^ B é uma proposição verdadeira se A e B o forem, e é uma proposição falsa, caso contrário; A B é uma proposição verdadeira se A ou B o forem, e falsa, caso contrário; ¬A é uma proposição verdadeira se A for falsa, e falsa se A for verdadeira. A partir dessas simples funções, Boole desenvolveu a lógica que é atualmente a base dos computadores digitais.

 

Figura 2.5 George Boole. Fonte: wikimedia.org.

Python possui operadores de comparação que fornecem resultados booleanos: <, <=, >, >=, ==, !=.

A Tabela 2.5 apresenta o significado de cada operador. Tabela 2.5 Operadores de comparação

Teste Símbolo

 

menor que <

 

menor ou igual que <=

 

maior que >

 

maior ou igual que <=

 

igual a ==

 

diferente de !=

 

O Programa 2.8 apresenta alguns desses operadores e o Programa 2.8a mostra o resultado de sua

execução. Note que podemos atribuir o resultado de uma comparação a uma variável e depois usar este valor no programa (comp_x_z = x != z).

x = 1

y = 2

z = 1

print (“x =”, x, “y =”, y, “z =”,z)

print (“x == y?”, x == y)

print (“x == z?”, x == z)

comp_x_z = x != z

print (“x != z?”, comp_x_z )

print (“x < y?”, x < y)

print (“y >= z?”, y >= z)

■ Programa 2.8: compara.py.

x = 1 y = 2 z = 1

x == y? False

x == z? True

x != z? False

x < y? True

y >= z? True

■ Programa 2.8a: Execução de compara.py.

Uma característica interessante de Python é poder fazer comparações encadeadas, como mostrado no Programa 2.9. Execute o programa e veja o resultado.

x = 2

print (“1 < x < 3”, 1 < x < 3)

print(“5 < x < 10”, 5 < x < 10)

print(“3 > x <= 2”, 3 > x <= 2)

print(“2 == x < 4”, 2 == x < 4)

■ Programa 2.9: comparav2.py.

Outro aspecto importante para o desenvolvimento de algoritmos é a manipulação de texto. Para ser

realmente útil, temos de interagir com o computador por meio de textos e também obter respostas mais complexas e escritas com letras, não apenas com números.

O que é um texto? Usamos tanto no nosso dia a dia que não paramos para pensar no que consiste

um texto escrito na tela de um computador. Um texto é uma sequência de caracteres. Esta é uma definição óbvia, porém importante. Esses caracteres podem ser as letras comuns do alfabeto, mas também podem ser símbolos, sinais de pontuação, números e até caracteres que não são visíveis diretamente, mas cujo efeito podemos perceber. Por exemplo, existe um caractere que faz seu editor de texto ou sua impressora passar para a próxima linha. Esse caractere é chamado, sem nenhuma surpresa, de “alimentador de linha”.

Uma sequência de caracteres ocupa alguma memória dentro do computador. Podemos usar um

identificador para referenciar a primeira posição desta sequência. A primeira posição define toda a sequência. Uma letra é colocada ao lado da outra, formando uma “cadeia de caracteres”. No jargão computacional, chamamos essas cadeias de strings, adotando o nome em inglês dessa abstração computacional. Até agora temos usado o que chamamos de “strings literais”, ou seja, cadeias de caracteres anônimas, sem um identificador explícito.

Os caracteres representam letras, dígitos e símbolos do alfabeto. Geralmente são representados

entre aspas simples, para diferenciar de outros símbolos usados nos programas. Assim, o caractere ‘A’, escrito entre aspas simples, é diferente do símbolo A dentro de um programa. Da mesma forma, dígitos escritos como caracteres, ‘2’, por exemplo, são diferentes dos valores do seu respectivo valor decimal, no caso, o número 2.

Cadeias de caracteres normalmente são apresentadas entre aspas duplas ou aspas simples.

Python usa um recurso interessante. Se você usar aspas simples para escrever uma string, pode escrever aspas duplas dentro da string. Se usar aspas duplas, essa string pode incluir aspas simples. A regra é que se você começa uma string com um tipo de aspas, deve terminá-la com o mesmo tipo.

print(“Gota d’água”)

print(‘Hamlet: “Ser ou não ser”’)

Quando escrevemos programas, dificilmente temos de nos preocupar com os valores binários ou

numéricos atribuídos aos dados não numéricos. Mesmo se no interior do computador tudo for convertido em números, estes valores devem ser ‘transparentes’ ao programador; isto quer dizer que o programador não deve se preocupar com esses valores internos e deve ignorá-los. Um algoritmo trabalha com abstrações. Criamos um modelo do mundo real dentro do computador, e assim devemos tratar essas abstrações e não os seus valores binários. Por outro lado, na hora de programar, ajuda saber como a linguagem de programação trata as strings.

Dica 2.13 – Comparação de strings.

Em um algoritmo, quando queremos comparar duas strings podemos simplesmente escrever o teste de igualdade:

x = ‘Supercalifragilisticexpialidocious!’

y = ‘Supercalifragilisticexpialidocious!’

Se x == y

imprima “São iguais”