Skip to content

Instantly share code, notes, and snippets.

@kieranb662
Last active October 16, 2020 17:34
Show Gist options
  • Save kieranb662/21579432280dbf918fb8bc9877d81d35 to your computer and use it in GitHub Desktop.
Save kieranb662/21579432280dbf918fb8bc9877d81d35 to your computer and use it in GitHub Desktop.
[Rational Number Type] Rational number implementation in swift #Math
import Foundation
struct RationalNumber {
let numerator: Int
let denominator: Int
// todo: fix this so that infinities are handled properly
var decimal: Double {
denominator != 0 ? Double(numerator)/Double(denominator) : .infinity
}
var magnitude: Double {
return abs(decimal)
}
public init(_ numerator: Int, _ denominator: Int) {
self.numerator = numerator
self.denominator = denominator
}
/// Need to test and refactor this to be more robust.
var isNegative: Bool {
if numerator >= 0 && denominator > 0 {
return false
} else if numerator <= 0 && denominator < 0 {
return false
} else {
return true
}
}
}
// MARK: - Equatable Conformance
extension RationalNumber: Equatable {
// todo: come back and adjust this because using the decimal is a bit of a naive
// approach to checking equivalence.
static func == (lhs: RationalNumber, rhs: RationalNumber) -> Bool {
return lhs.decimal == rhs.decimal
}
}
// MARK: - Comparable Conformance
extension RationalNumber: Comparable {
// todo: Come back and fix for same reason as Equatable.
static func < (lhs: RationalNumber, rhs: RationalNumber) -> Bool {
return lhs.decimal < rhs.decimal
}
}
// MARK: - Int and Rational Math
/// Compute the value of a rational number to the power of an integer.
/// The three main cases are handled
/// * power greater than 0
/// * power less than 0
/// * power equal to 0
/// - important- Relies on a for loop to multiply the numerator and denominator by its self (power-1) times. This could be very slow for large powers.
func pow(base: RationalNumber, power: Int) -> RationalNumber {
if power == 0 {
return 1
} else {
var num = base.numerator
var denom = base.denominator
for _ in 1...abs(power)-1 {
num *= base.numerator
denom *= base.denominator
}
return power > 0 ? RationalNumber(num, denom) : RationalNumber(denom, num)
}
}
// MARK: AdditiveArithmetic Conformance
extension RationalNumber: AdditiveArithmetic {
static var zero: RationalNumber = 0
static func += (lhs: inout RationalNumber, rhs: RationalNumber) {
lhs = lhs+rhs
}
static func -= (lhs: inout RationalNumber, rhs: RationalNumber) {
lhs = lhs-rhs
}
}
// MARK: - (Rational, Rational) Math
extension RationalNumber {
static func *(lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
return RationalNumber(lhs.numerator*rhs.numerator,
lhs.denominator*rhs.denominator)
}
static func /(lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
return RationalNumber(lhs.numerator*rhs.denominator,
lhs.denominator*rhs.numerator)
}
static func +(lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
return RationalNumber(lhs.numerator*rhs.denominator + lhs.denominator*rhs.numerator,
lhs.denominator*rhs.denominator)
}
static func -(lhs: RationalNumber, rhs: RationalNumber) -> RationalNumber {
return RationalNumber(lhs.numerator*rhs.denominator - lhs.denominator*rhs.numerator,
lhs.denominator*rhs.denominator)
}
static func ^(lhs: RationalNumber, rhs: Int) -> RationalNumber {
return pow(base: lhs, power: rhs)
}
static prefix func -(input: RationalNumber) -> RationalNumber {
return RationalNumber(-input.numerator, input.denominator)
}
}
// MARK: - ExpressibleByIntegerLiteral Conformance
extension RationalNumber: ExpressibleByIntegerLiteral {
init(integerLiteral value: Int) {
numerator = value
denominator = 1
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment