Percursos
/
Julia
Julia
/
Exercícios
/
Câmbio de moedas
Câmbio de moedas

Câmbio de moedas

Exercício de aprendizagem

Introdução

A Julia é uma linguagem de uso geral que pode ser usada na maioria das tarefas de programação. Na prática, porém, as principais utilizações tendem a ser na engenharia e na ciência. Os cálculos numéricos rápidos, versáteis e sofisticados estão no centro da sua conceção.

Números inteiros

Um número inteiro é um número "redondo", sem vírgula decimal.

No conceito Básicos, vimos que é possível atribuir um valor inteiro a uma variável sem especificar o tipo.

Para facilitar a leitura, podem usar-se underscores como separador de algarismos. O compilador ignora-os.

julia> x = 3
3

julia> typeof(x)
Int64

julia> large_number = 1_234_567_890
1234567890

Vírgula flutuante

Não é surpresa que os números de vírgula flutuante tenham uma vírgula decimal, e uma parte fracionária depois da vírgula.

julia> f = 3.45
3.45

julia> typeof(f)
Float64

Claro que a notação científica é suportada.

julia> avogadro = 6.02e23
6.02e23

Os valores máximo e mínimo podem surpreender-te:

julia> typemax(Float64)
Inf

julia> typemin(Float64)
-Inf

O infinito é um valor válido!

Operadores aritméticos

Como vimos no conceito Básicos, os operadores aritméticos funcionam, na maioria dos casos, como na aritmética normal, aquela que aprendemos em criança. Repara que a exponenciação usa ^, e não ** (ambos são comuns noutras linguagens).

2 + 3  # 5 (addition)
2 - 3  # -1 (subtraction)
2 * 3  # 6 (multiplication)
8 / 2  # 4.0 (division)
8 % 3  # 2 (remainder)
2 ^ 3  # 8 (exponentiation)

No entanto, há alguns pormenores específicos da Julia que vale a pena discutir.

Multiplicação

julia> x = 4.2
4.2

julia> 2 * x
8.4

julia> 2x
8.4

julia> 2.4x
10.08

Isso pode ser surpreendente.

É sempre possível usar * como operador infixo, como na maioria das outras linguagens de programação.

No entanto, a Julia foi criada por pessoas que acreditam que o código deve parecer-se o mais possível com equações matemáticas.

Como os nomes de variáveis têm de começar por uma letra, colocar um número (inteiro ou de vírgula flutuante) antes do nome é tratado como multiplicação implícita.

Por exemplo, se quisermos a área da superfície de uma esfera, em vez de 4 * pi * r * r podemos fazer isto:

julia> surface(r) = 4π * r^2
surface (generic function with 1 method)

julia> surface(3)
113.09733552923255

Embora o π seja uma constante incorporada, também é uma letra (grega). Por isso, o analisador sintático continua a precisar de um * explícito para separar o π do r.

Divisão

Usar / como operador infixo dá sempre um resultado de vírgula flutuante, mesmo para valores de entrada inteiros.

Para a divisão inteira, há mais opções.

julia> 10 / 3  # floating-point division
3.3333333333333335

julia> div(10, 3)  # integer division
3

julia> 10 ÷ 3  # synonym for div()
3

julia> 10 // 3  # rational number (fraction)
10//3

A função div() serve para a divisão inteira e trunca o resultado em direção ao zero: para baixo nos números positivos, para cima nos negativos.

Como sinónimo, podemos usar o operador infixo ÷, mais uma vez para o tornar mais matemático. Se estiveres a usar um editor com suporte para Julia, escreve \div e a seguir prime a tecla <Tab>.

O operador // está para lá do âmbito deste conceito. Por agora, basta dizer que o resultado de // é um número "racional", aquilo a que a maioria das pessoas chama fração.

Conversão de tipos numéricos

Isto pode acontecer automaticamente muitas vezes:

julia> x = 2 + 3.5
5.5

julia> typeof(x)
Float64

Somámos um Int64 a um Float64 e obtivemos um resultado Float64.

Na verdade, o número inteiro foi convertido silenciosamente num Float64 antes de se fazer a adição.

As conversões de vírgula flutuante para inteiro são inevitavelmente mais complicadas. O que queres fazer com o que vem depois da vírgula decimal?

  • A função round() converte para o número inteiro mais próximo, com os empates, como 4.5, a arredondar para o número inteiro par mais próximo.
  • floor() arredonda para baixo, ceil() arredonda para cima, trunc() arredonda em direção ao zero.
  • Tentar converter diretamente, por exemplo com Int32(), dá origem a um InexactError.

No entanto, por predefinição, estas funções não devolvem o tipo inteiro que poderias querer. É possível especificar o tipo de resultado pretendido.

julia> round(4.5)
4.0

julia> ceil(Int, 4.3)
5

Também é possível arredondar para um número especificado de algarismos depois da vírgula decimal, através da palavra-chave digits.

julia> round(π, digits=10)
3.1415926536

Divisão por zero

Certamente que isto dá logo um erro? Na verdade, a situação não é assim tão simples.

A divisão inteira com ÷ ou // dá um erro, como seria de esperar.

A divisão de vírgula flutuante com / segue uma abordagem que se pode considerar de engenharia, em vez da abordagem padrão da informática:

julia> 2 / 0
Inf

julia> 0 / 0
NaN

Como vimos numa secção anterior, o infinito é um número de vírgula flutuante válido na Julia, representado por Inf.

Quando o numerador também é zero, o resultado é matematicamente indefinido. A Julia trata-o então como "não é um número", representado por NaN.

Instruções

O teu amigo Chandler planeia visitar países exóticos por todo o mundo. Infelizmente, o Chandler não é bom a matemática. Está bastante preocupado em ser enganado nos câmbios durante a viagem, e quer que lhe faças uma calculadora de moedas. Aqui estão as especificações dele para a aplicação:

1. Estima o valor depois da troca

Cria a função exchange_money(), que recebe 2 parâmetros:

  1. budget: a quantia de dinheiro que planeias trocar.
  2. exchange_rate: a quantidade de moeda nacional equivalente a uma unidade de moeda estrangeira.

Esta função deve devolver o valor da moeda trocada.

Nota: se a tua moeda for o USD e quiseres trocar USD por EUR com uma taxa de câmbio de 1.20, então 1.20 USD == 1 EUR.

julia> exchange_money(127.5, 1.2)
106.25

2. Calcula a moeda restante depois de uma troca

Cria a função get_change(), que recebe 2 parâmetros:

  1. budget: a quantidade de dinheiro antes da troca.
  2. exchanging_value: a quantidade de dinheiro que é retirada do orçamento para ser trocada.

Esta função deve devolver a quantidade de dinheiro que sobra do orçamento.

julia> get_change(127.5, 120)
7.5

3. Calcula o valor das notas

Cria a função get_value_of_bills(), que recebe 2 parâmetros:

  1. denomination: o valor de uma única nota.
  2. number_of_bills: o número total de notas.

Este posto de câmbio só lida com dinheiro em incrementos específicos. O total que recebes tem de ser divisível pelo valor de uma "nota" ou unidade, o que pode deixar uma fração ou um resto. A tua função deve devolver apenas o valor total das notas (excluindo quantias fracionárias) que o posto devolveria. Infelizmente, o posto fica com o resto/troco como bónus adicional.

julia> get_value_of_bills(5, 128)
640

4. Calcula o número de notas

Cria a função get_number_of_bills(), que recebe amount e denomination.

Esta função deve devolver o número de notas que podes receber dentro do amount indicado. Por outras palavras: quantas notas inteiras cabem na quantia inicial? Lembra-te de que só podes receber notas inteiras, não frações de notas, por isso não te esqueças de dividir em conformidade. Na prática, estás a arredondar para baixo para a nota/denominação inteira mais próxima.

julia> get_number_of_bills(127.5, 5)
25

5. Calcula o que sobra depois de trocar por notas

Cria a função get_leftover_of_bills(), que recebe amount e denomination.

Esta função deve devolver a quantia restante que não pode ser devolvida a partir do teu amount inicial, dada a denominação das notas. É muito importante saber exatamente quanto é que o posto acaba por ficar.

julia> get_leftover_of_bills(127.5, 20)
7.5

6. Calcula o valor depois da troca

Cria a função exchangeable_value(), que recebe budget, exchange_rate, spread e denomination.

O parâmetro spread é a percentagem retirada como comissão de câmbio, escrita como um número inteiro. Tem de ser convertida em decimal dividindo-a por 100. Se 1.00 EUR == 1.20 USD e o spread for 10, a taxa de câmbio total será, na verdade: 1.00 EUR == 1.32 USD, porque 10% de 1.20 é 0.12, e esta comissão adicional é somada ao câmbio.

Esta função deve devolver o valor máximo da nova moeda depois de calcular a taxa de câmbio mais o spread. Lembra-te de que a denominação da moeda é um número inteiro e não pode ser subdividida.

Nota: o valor devolvido deve ser do tipo inteiro.

julia> exchangeable_value(127.25, 1.20, 10, 20)
80

julia> exchangeable_value(127.25, 1.20, 10, 5)
95
Editar via GitHub A ligação abre numa nova janela ou separador
Julia Exercism

Estás pronto para começar Câmbio de moedas?

Inscreve-te no Exercism para aprenderes e dominares Julia com 35 conceitos128 exercícios, e mentoria humana real, tudo grátis.