A rational number is defined as the quotient of two integers a
and b
, called the numerator and denominator, respectively, where b != 0
.
The absolute value |r|
of the rational number r = a/b
is equal to |a|/|b|
.
The sum of two rational numbers r1 = a1/b1
and r2 = a2/b2
is r1 + r2 = a1/b1 + a2/b2 = (a1 * b2 + a2 * b1) / (b1 * b2)
.
The difference of two rational numbers r1 = a1/b1
and r2 = a2/b2
is r1 - r2 = a1/b1 - a2/b2 = (a1 * b2 - a2 * b1) / (b1 * b2)
.
The product (multiplication) of two rational numbers r1 = a1/b1
and r2 = a2/b2
is r1 * r2 = (a1 * a2) / (b1 * b2)
.
Dividing a rational number r1 = a1/b1
by another r2 = a2/b2
is r1 / r2 = (a1 * b2) / (a2 * b1)
if a2 * b1
is not zero.
Exponentiation of a rational number r = a/b
to a non-negative integer power n
is r^n = (a^n)/(b^n)
.
Exponentiation of a rational number r = a/b
to a negative integer power n
is r^n = (b^m)/(a^m)
, where m = |n|
.
Exponentiation of a rational number r = a/b
to a real (floating-point) number x
is the quotient (a^x)/(b^x)
, which is a real number.
Exponentiation of a real number x
to a rational number r = a/b
is x^(a/b) = root(x^a, b)
, where root(p, q)
is the q
th root of p
.
Implement the following operations:
Your implementation of rational numbers should always be reduced to lowest terms. For example, 4/4
should reduce to 1/1
, 30/60
should reduce to 1/2
, 12/8
should reduce to 3/2
, etc. To reduce a rational number r = a/b
, divide a
and b
by the greatest common divisor (gcd) of a
and b
. So, for example, gcd(12, 8) = 4
, so r = 12/8
can be reduced to (12/4)/(8/4) = 3/2
.
Assume that the programming language you are using does not have an implementation of rational numbers.
Wikipedia https://en.wikipedia.org/wiki/Rational_number
This exercise has been tested on Julia versions >=1.0.
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
In [ ]:
# submit
In [ ]:
using Test
# include("rational-numbers.jl")
@test RationalNumber <: Real
@test_throws ArgumentError RationalNumber(0, 0)
@testset "One- & Zero-elements" begin
@test zero(RationalNumber{Int}) == RationalNumber(0, 1)
@test one(RationalNumber{Int}) == RationalNumber(1, 1)
end
@testset "Arithmetic" begin
@testset "Addition" begin
@test RationalNumber( 1, 2) + RationalNumber( 2, 3) == RationalNumber( 7, 6)
@test RationalNumber( 1, 2) + RationalNumber(-2, 3) == RationalNumber(-1, 6)
@test RationalNumber(-1, 2) + RationalNumber(-2, 3) == RationalNumber(-7, 6)
@test RationalNumber( 1, 2) + RationalNumber(-1, 2) == RationalNumber( 0, 1)
end
@testset "Subtraction" begin
@test RationalNumber( 1, 2) - RationalNumber( 2, 3) == RationalNumber(-1, 6)
@test RationalNumber( 1, 2) - RationalNumber(-2, 3) == RationalNumber( 7, 6)
@test RationalNumber(-1, 2) - RationalNumber(-2, 3) == RationalNumber( 1, 6)
@test RationalNumber( 1, 2) - RationalNumber( 1, 2) == RationalNumber( 0, 1)
end
@testset "Multiplication" begin
@test RationalNumber( 1, 2) * RationalNumber( 2, 3) == RationalNumber( 1, 3)
@test RationalNumber(-1, 2) * RationalNumber( 2, 3) == RationalNumber(-1, 3)
@test RationalNumber(-1, 2) * RationalNumber(-2, 3) == RationalNumber( 1, 3)
@test RationalNumber( 1, 2) * RationalNumber( 2, 1) == RationalNumber( 1, 1)
@test RationalNumber( 1, 2) * RationalNumber( 1, 1) == RationalNumber( 1, 2)
@test RationalNumber( 1, 2) * RationalNumber( 0, 1) == RationalNumber( 0, 1)
end
@testset "Exponentiation" begin
@testset "Exponentiation of a rational number" begin
@test RationalNumber( 1, 2)^3 == RationalNumber( 1, 8)
@test RationalNumber(-1, 2)^3 == RationalNumber(-1, 8)
@test RationalNumber( 0, 1)^5 == RationalNumber( 0, 1)
@test RationalNumber( 1, 1)^4 == RationalNumber( 1, 1)
@test RationalNumber( 1, 2)^0 == RationalNumber( 1, 1)
@test RationalNumber(-1, 2)^0 == RationalNumber( 1, 1)
end
@testset "Exponentiation of a real number to a rational number" begin
@test 8^RationalNumber( 4, 3) == 15.999999999999998
@test 9^RationalNumber(-1, 2) == 0.3333333333333333
@test 2^RationalNumber( 0, 1) == 1.0
end
end
@testset "Division" begin
@test RationalNumber( 1, 2) / RationalNumber( 2, 3) == RationalNumber( 3, 4)
@test RationalNumber( 1, 2) / RationalNumber(-2, 3) == RationalNumber(-3, 4)
@test RationalNumber(-1, 2) / RationalNumber(-2, 3) == RationalNumber( 3, 4)
@test RationalNumber( 1, 2) / RationalNumber( 1, 1) == RationalNumber( 1, 2)
end
end
@testset "Absolute value" begin
@test abs(RationalNumber( 1, 2)) == RationalNumber(1, 2)
@test abs(RationalNumber(-1, 2)) == RationalNumber(1, 2)
@test abs(RationalNumber( 0, 1)) == RationalNumber(0, 1)
@test abs(RationalNumber( 1, -2)) == RationalNumber(1, 2)
end
@testset "Reduction to lowest terms" begin
r = RationalNumber(2, 4)
@test numerator(r) == 1
@test denominator(r) == 2
r = RationalNumber(-4, 6)
@test numerator(r) == -2
@test denominator(r) == 3
r = RationalNumber(3, -9)
@test numerator(r) == -1
@test denominator(r) == 3
r = RationalNumber(0, 6)
@test numerator(r) == 0
@test denominator(r) == 1
r = RationalNumber(-14, 7)
@test numerator(r) == -2
@test denominator(r) == 1
r = RationalNumber(13, 13)
@test numerator(r) == 1
@test denominator(r) == 1
r = RationalNumber(1, -1)
@test numerator(r) == -1
@test denominator(r) == 1
end
# TODO add to problem spec
# The following testset is based on the tests for rational numbers in Julia Base (MIT license)
# https://github.com/JuliaLang/julia/blob/52bafeb981bac548afd2264edb518d8d86944dca/test/rational.jl
# https://github.com/JuliaLang/julia/blob/52bafeb981bac548afd2264edb518d8d86944dca/LICENSE.md
@testset "Ordering" begin
for a in -5:5, b in -5:5, c in -5:5
a == b == 0 && continue
r = RationalNumber(a, b)
@test (r == c) == (a / b == c)
@test (r != c) == (a / b != c)
@test (r <= c) == (a / b <= c)
@test (r < c) == (a / b < c)
@test (r >= c) == (a / b >= c)
@test (r > c) == (a / b > c)
for d in -5:5
c == d == 0 && continue
s = RationalNumber(c, d)
@test (r == s) == (a / b == c / d)
@test (r != s) == (a / b != c / d)
@test (r <= s) == (a / b <= c / d)
@test (r < s) == (a / b < c / d)
@test (r >= s) == (a / b >= c / d)
@test (r > s) == (a / b > c / d)
end
end
end
@testset "Showing RationalNumbers" begin
@test sprint(show, RationalNumber(23, 42)) == "23//42"
@test sprint(show, RationalNumber(-2500, 5000)) == "-1//2"
end
To submit your exercise, you need to save your solution in a file called rational-numbers.jl
before using the CLI.
You can either create it manually or use the following functions, which will automatically write every notebook cell that starts with # submit
to the file rational-numbers.jl
.
In [ ]:
# using Pkg; Pkg.add("Exercism")
# using Exercism
# Exercism.create_submission("rational-numbers")