8.8 KiB
Currency Exchange
Welcome to Currency Exchange on Exercism’s Julia Track. If you need
help running the tests or submitting your code, check out
HELP.md. If you get stuck on the exercise, check out
HINTS.md, but try and solve it without using those first
:)
Introduction
Julia is a general-purpose language that can be used for most programming tasks. In practice, however, the main use cases tend to be in engineering and science. Fast, versatile, sophisticated numerical calculations are central to the design.
Integers
An integer is a “round” number with no decimal point.
In the Basics concept, we saw that an integer value can be assigned to a variable without specifying a type.
For readability, underscores can be used as a digit separator. They are ignored by the compiler.
julia> x = 3
3
julia> typeof(x)
Int64
julia> large_number = 1_234_567_890
1234567890
Floating-point
It will be no surprise that floating-point numbers have a decimal point, and a fractional part after the point.
julia> f = 3.45
3.45
julia> typeof(f)
Float64
Of course, scientific notation is supported.
julia> avogadro = 6.02e23
6.02e23
The maximum and minimum values may come as a surprise:
julia> typemax(Float64)
Inf
julia> typemin(Float64)
-Inf
Infinity is a valid value!
Arithmetic operators
As discussed in the Basics concept, arithmetic operators mostly work
the same as standard arithmetic, as taught to children. Note that
exponentiation uses ^, not ** (both
are common in other languages).
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)However, a few Julia-specific details are worth discussing.
Multiplication
julia> x = 4.2
4.2
julia> 2 * x
8.4
julia> 2x
8.4
julia> 2.4x
10.08
That may be surprising.
It is always possible to use * as an infix operator, as
in most other computer languages.
However, Julia is designed by people who believe that code should look as much as possible like mathematical equations.
Because variable names must start with a letter, prefacing the name with a number (integer or floating-point) is treated as implicit multiplication.
For example, if we want the surface area of a sphere, instead of
4 * pi * r * r we could do this :
julia> surface(r) = 4π * r^2
surface (generic function with 1 method)
julia> surface(3)
113.09733552923255
Although π is a built-in constant, it is also a (Greek) letter. The
parser therefore still needs one explicit * to separate
π from r.
Division
Using / as the infix operator will always give a
floating-point result, even for integer inputs.
For integer division, there are more options.
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
The div() function is for integer division, with the
result truncated towards zero: downwards for positive numbers, upwards
for negative numbers.
As a synonym, we can use the infix operator ÷, again
aiming to make it look more mathematical. If you are using a Julia-aware
editor, enter this as \div then hit the
<Tab> key.
The // operator is beyond the scope of this Concept. For
now, we can just say that the result of // is a “rational”
number, which most people call a fraction.
Conversion of numeric types
This can often happen automatically:
julia> x = 2 + 3.5
5.5
julia> typeof(x)
Float64
We added an Int64 to a Float64, and got a
Float64 result.
In fact, the integer was silently converted to a Float64
before doing the addition.
Float-to-integer conversions are inevitably more complicated. What do you want to do with anything after the decimal point?
- The
round()function converts to the nearest whole number, with ties such as 4.5 rounding to the nearest even whole number. floor()rounds down,ceil()rounds up,trunc()rounds towards zero.- Attempting to cast directly, for example with
Int32(), will fail with anInexactError.
However, by default these functions do not return the integer type you might have wanted. The desired output type can be specified.
julia> round(4.5)
4.0
julia> ceil(Int, 4.3)
5
Rounding to a specified number of digits after the decimal point is
also possible with the digits keyword.
julia> round(π, digits=10)
3.1415926536
Divide-by-zero
Surely this just throws an error? In fact, the situation is not that simple.
Integer division with ÷ or // will result
in an error, as you might expect.
Floating-point division with / takes what might be
considered an engineering approach, rather than a standard computer
science approach:
julia> 2 / 0
Inf
julia> 0 / 0
NaN
As discussed in a previous section, infinity is a valid
floating-point number in Julia, represented by Inf.
When the numerator is also zero, the result is mathematically
undefined. Julia then treats it as “not a number”, represented by
NaN.
Instructions
Your friend Chandler plans to visit exotic countries all around the world. Sadly, Chandler’s math skills aren’t good. He’s pretty worried about being scammed by currency exchanges during his trip - and he wants you to make a currency calculator for him. Here are his specifications for the app:
1. Estimate value after exchange
Create the exchange_money() function, taking 2
parameters:
budget: The amount of money you are planning to exchange.exchange_rate: The amount of domestic currency equal to one unit of foreign currency.
This function should return the value of the exchanged currency.
Note: If your currency is USD and you want to
exchange USD for EUR with an exchange rate of 1.20, then
1.20 USD == 1 EUR.
julia> exchange_money(127.5, 1.2)
106.252. Calculate currency left after an exchange
Create the get_change() function, taking 2
parameters:
budget: Amount of money before exchange.exchanging_value: Amount of money that is taken from the budget to be exchanged.
This function should return the amount of money that is left from the budget.
julia> get_change(127.5, 120)
7.53. Calculate value of bills
Create the get_value_of_bills() function, taking 2
parameters:
denomination: The value of a single bill.number_of_bills: The total number of bills.
This exchanging booth only deals in cash of certain increments. The total you receive must be divisible by the value of one “bill” or unit, which can leave behind a fraction or remainder. Your function should return only the total value of the bills (excluding fractional amounts) the booth would give back. Unfortunately, the booth gets to keep the remainder/change as an added bonus.
julia> get_value_of_bills(5, 128)
6404. Calculate number of bills
Create the get_number_of_bills() function, taking
amount and denomination.
This function should return the number of currency bills that you can receive within the given amount. In other words: How many whole bills of currency fit into the starting amount? Remember – you can only receive whole bills, not fractions of bills, so remember to divide accordingly. Effectively, you are rounding down to the nearest whole bill/denomination.
julia> get_number_of_bills(127.5, 5)
255. Calculate leftover after exchanging into bills
Create the get_leftover_of_bills() function, taking
amount and denomination.
This function should return the leftover amount that cannot be returned from your starting amount given the denomination of bills. It is very important to know exactly how much the booth gets to keep.
julia> get_leftover_of_bills(127.5, 20)
7.56. Calculate value after exchange
Create the exchangeable_value() function, taking
budget, exchange_rate, spread,
and denomination.
Parameter spread is the percentage taken as an
exchange fee, written as an integer. It needs to be converted to decimal
by dividing it by 100. If 1.00 EUR == 1.20 USD and the
spread is 10, the actual exchange rate will be:
1.00 EUR == 1.32 USD because 10% of 1.20 is 0.12, and this
additional fee is added to the exchange.
This function should return the maximum value of the new currency after calculating the exchange rate plus the spread. Remember that the currency denomination is a whole number, and cannot be sub-divided.
Note: Returned value should be an integer type.
julia> exchangeable_value(127.25, 1.20, 10, 20)
80
julia> exchangeable_value(127.25, 1.20, 10, 5)
95Source
Created by
- @colinleach