Created
July 21, 2017 20:13
-
-
Save natecook1000/27d31d73315ffc2c80a7b4efc5788bd0 to your computer and use it in GitHub Desktop.
FloatingPoint conformance for Decimal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Decimal.RoundingMode { | |
init(_ rule: FloatingPointRoundingRule, for value: Decimal) { | |
switch rule { | |
case .down: self = .down | |
case .up: self = .up | |
case .awayFromZero: self = value < 0 ? .down : .up | |
case .towardZero: self = value < 0 ? .up : .down | |
case .toNearestOrAwayFromZero: self = .plain | |
case .toNearestOrEven: self = .bankers | |
} | |
} | |
} | |
extension Decimal : FloatingPoint { | |
public mutating func round(_ rule: FloatingPointRoundingRule) { | |
var original = self | |
NSDecimalRound(&self, &original, 0, .init(rule, for: self)) | |
} | |
public mutating func formRemainder(dividingBy other: Decimal) { | |
let q = (self / other).rounded(.toNearestOrEven) | |
self -= other * q | |
} | |
public mutating func formSquareRoot() { | |
guard !isZero else { return } | |
guard self > 0 else { self = .nan; return } | |
var guess: Decimal = 1 | |
for _ in 0..<10 { | |
guess = ((self / guess) + guess) / 2 | |
} | |
self = guess | |
} | |
public mutating func addProduct(_ lhs: Decimal, _ rhs: Decimal) { | |
self += lhs * rhs | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Sequence where Element : FloatingPoint { | |
func runningAverage() -> AnySequence<Element> { | |
typealias State = (iterator: Iterator, count: Element, lastTotal: Element) | |
return AnySequence(sequence(state: (makeIterator(), 0, 0), next: { (state: inout State) -> Element? in | |
guard let value = state.iterator.next() else { return nil } | |
state.count += 1 | |
state.lastTotal += value | |
return state.lastTotal / state.count | |
})) | |
} | |
} | |
let values: [Decimal] = [3, 3.1, 3.5, 2.9, 2.5, 3, 7] | |
for x in values.runningAverage() { | |
print(x) | |
} | |
/* | |
3 | |
3.05 | |
3.2 | |
3.125 | |
3 | |
3 | |
3.5714285714285714285714285714285714285 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment