import Foundation extension Decimal { // MARK: - Formatting var currencyString: String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencyCode = "EUR" formatter.maximumFractionDigits = 2 return formatter.string(from: self as NSDecimalNumber) ?? "€0.00" } var compactCurrencyString: String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencyCode = "EUR" formatter.maximumFractionDigits = 0 return formatter.string(from: self as NSDecimalNumber) ?? "€0" } var shortCurrencyString: String { let value = NSDecimalNumber(decimal: self).doubleValue switch abs(value) { case 1_000_000...: return String(format: "€%.1fM", value / 1_000_000) case 1_000...: return String(format: "€%.1fK", value / 1_000) default: return compactCurrencyString } } var percentageString: String { let formatter = NumberFormatter() formatter.numberStyle = .percent formatter.maximumFractionDigits = 2 formatter.multiplier = 1 return formatter.string(from: self as NSDecimalNumber) ?? "0%" } var signedPercentageString: String { let prefix = self >= 0 ? "+" : "" return prefix + percentageString } var decimalString: String { let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.maximumFractionDigits = 2 return formatter.string(from: self as NSDecimalNumber) ?? "0" } // MARK: - Conversions var doubleValue: Double { NSDecimalNumber(decimal: self).doubleValue } var intValue: Int { NSDecimalNumber(decimal: self).intValue } // MARK: - Math Operations var abs: Decimal { self < 0 ? -self : self } func rounded(scale: Int = 2) -> Decimal { var result = Decimal() var mutableSelf = self NSDecimalRound(&result, &mutableSelf, scale, .plain) return result } // MARK: - Comparisons var isPositive: Bool { self > 0 } var isNegative: Bool { self < 0 } var isZero: Bool { self == 0 } // MARK: - Static Helpers static func from(_ double: Double) -> Decimal { Decimal(double) } static func from(_ string: String) -> Decimal? { let formatter = NumberFormatter() formatter.numberStyle = .decimal return formatter.number(from: string)?.decimalValue } } // MARK: - NSDecimalNumber Extension extension NSDecimalNumber { var currencyString: String { decimalValue.currencyString } var compactCurrencyString: String { decimalValue.compactCurrencyString } } // MARK: - Optional Decimal extension Optional where Wrapped == Decimal { var orZero: Decimal { self ?? Decimal.zero } var currencyString: String { (self ?? Decimal.zero).currencyString } }