Skip to content

Instantly share code, notes, and snippets.

@BlueRayi
Created September 10, 2018 11:26
Show Gist options
  • Save BlueRayi/5bba14d9a27cceecb5764b429a032289 to your computer and use it in GitHub Desktop.
Save BlueRayi/5bba14d9a27cceecb5764b429a032289 to your computer and use it in GitHub Desktop.
有理数構造体(貧弱)
prefix operator /
public prefix func +(rhs: Rational) -> Rational // これいる?
{
return Rational(rhs.pee, rhs.cue)
}
public prefix func -(rhs: Rational) -> Rational // 反数
{
return Rational(-rhs.pee, rhs.cue)
}
public prefix func /(rhs: Rational) -> Rational // 逆数
{
if rhs.pee < 0 {
return Rational(-rhs.cue, -rhs.pee)
} else {
return Rational(rhs.cue, rhs.pee)
}
}
public func +(lhs: Rational, rhs: Rational) -> Rational
{
return Rational(lhs.pee * rhs.cue + rhs.pee * lhs.cue, lhs.cue * rhs.cue) // 1/0を無限遠点とする実装
}
public func -(lhs: Rational, rhs: Rational) -> Rational
{
return lhs + (-rhs)
}
public func *(lhs: Rational, rhs: Rational) -> Rational
{
return Rational(lhs.pee * rhs.pee, lhs.cue * rhs.cue)
}
public func /(lhs: Rational, rhs: Rational) -> Rational
{
return lhs * (/rhs)
}
public func +=(lhs: inout Rational, rhs: Rational)
{
lhs = lhs + rhs
}
public func -=(lhs: inout Rational, rhs: Rational)
{
lhs = lhs - rhs
}
public func *=(lhs: inout Rational, rhs: Rational)
{
lhs = lhs * rhs
}
public func /=(lhs: inout Rational, rhs: Rational)
{
lhs = lhs / rhs
}
public func ==(lhs: Rational, rhs: Rational) -> Bool
{
if lhs.isIndeterminate || rhs.isIndeterminate { // 1/0を無限遠点とする実装
return false
} else {
return lhs.pee * rhs.cue == rhs.pee * lhs.cue
}
}
public func !=(lhs: Rational, rhs: Rational) -> Bool
{
return !(lhs == rhs)
}
public func <(lhs: Rational, rhs: Rational) -> Bool
{
if lhs.isIndeterminate || rhs.isIndeterminate {
return false
} else {
if lhs.isInfinite { // 1/0を無限遠点とする実装
if rhs.pee < 0 {
return true
} else {
return false
}
} else if rhs.isInfinite { // 1/0を無限遠点とする実装
if lhs.pee > 0 {
return true
} else {
return false
}
} else {
return lhs.pee * rhs.cue < rhs.pee * lhs.cue
}
}
}
public func <=(lhs: Rational, rhs: Rational) -> Bool
{
return lhs == rhs || lhs < rhs
}
public func >(lhs: Rational, rhs: Rational) -> Bool
{
if lhs.isIndeterminate || rhs.isIndeterminate {
return false
} else {
if lhs.isInfinite { // 1/0を無限遠点とする実装
if rhs.pee > 0 {
return true
} else {
return false
}
} else if rhs.isInfinite { // 1/0を無限遠点とする実装
if lhs.pee < 0 {
return true
} else {
return false
}
} else {
return lhs.pee * rhs.cue > rhs.pee * lhs.cue
}
}
}
public func >=(lhs: Rational, rhs: Rational) -> Bool
{
return lhs == rhs || lhs > rhs
}
extension Rational: ExpressibleByIntegerLiteral
{
public init(integerLiteral value: IntegerLiteralType)
{
self.init(value)
}
}
extension Rational: CustomStringConvertible
{
public var description: String {
switch self.cue {
case 1:
return "\(self.pee)"
case 0:
switch self.pee { // 1/0を無限遠点とする実装
case 1:
return "∞"
case 0:
return "不定形"
default:
return "メッセージは出ないはずだよ"
}
default:
return Rational.sup(self.pee) + "/" + Rational.sub(self.cue)
}
}
}
public struct Rational: Equatable
{
fileprivate let pee: Int
fileprivate let cue: Int
public var numer: Int { return self.pee }
public var denom: Int { return self.cue }
public var isFinite: Bool { return self.cue != 0 }
public var isInfinite: Bool { return self.cue == 0 && self.pee != 0}
public var isIndeterminate: Bool { return self.cue == 0 && self.pee == 0 }
public init(_ pee: Int, _ cue: Int)
{
let xxx = Rational.gcd(pee, cue)
if cue == 0 { // 1/0を無限遠点とする実装
self.cue = 0
if pee == 0 {
self.pee = 0
} else {
self.pee = 1
}
} else {
if (xxx < 0) == (cue < 0) {
self.pee = pee / xxx
self.cue = cue / xxx
} else {
self.pee = -pee / xxx
self.cue = -cue / xxx
}
}
}
public init(_ pee: Int)
{
self.pee = pee
self.cue = 1
}
fileprivate static func gcd(_ a: Int, _ b: Int) -> Int
{
switch b {
case 0:
return a
default:
return gcd(b, a % b)
}
}
fileprivate static func sup(_ number: Int) -> String
{
return String(number)
}
fileprivate static func sub(_ number: Int) -> String
{
return String(number)
}
}
var foo = Rational(2)
print(foo) // 2
foo = Rational(2, 4)
print(foo) // 1/2
print("約分も当然できます")
foo = 3
print(foo) // 3
print("\(foo)の反数は\(-foo)、逆数は\(/foo)") // 3の反数は-3、逆数は1/3
var bar = Rational(9, 5)
print("\(foo) ÷ \(bar) = \(foo / bar)") //3 ÷ 9/5 = 5/3
print("計算結果も約分します")
foo = 5
bar = 0
print("ゼロ除算…5/0 = \(foo / bar)、0/0 = \(bar / bar)") // 5/0 = ∞、0/0 = 不定形
print("定番の二進数丸め誤差誤差計算は?")
let float = 0.1
let rational = Rational(1, 10)
var floatSum: Double = 0
var rationalSum: Rational = 0
for _ in 0 ..< 10 {
floatSum += float
rationalSum += rational
}
print("float: \(float) * 10 = 1.0? -> \(floatSum)…しかし\(floatSum == 1.0)") // 1.0…しかしfalse
print("rational: \(rational) * 10 = 1? -> \(rationalSum)…当然\(rationalSum == 1)") // 1…当然true
print("素晴らしきかな有理数!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment