Contents

swift-atoms/swift-decimal

Use this package when you need IEEE 754 decimal floating point: values such as money or measurements that must round in base ten and that need the standard rounding, flags and special values. The Decimal product holds the three interchange formats Decimal.Format32, `Decimal.F

Laws

  • A value is its coefficient × 10^exponent. Decimal.Exponent limits such as maxExponent and minExponent bound that quantum exponent. Decimal.Exponent.Format64.scientificMin and its siblings bound the adjusted exponent, which is the exponent of the leading digit. A finite nonzero value is .subnormal exactly when its adjusted exponent is below scientificMin.
  • == and hash(into:) compare numeric values, not encodings. Members of one cohort (1 and 1.00) are equal and hash alike. Zeros are equal whatever their sign or exponent. NaN is unequal to everything, itself included. Infinities are equal only when their signs match. A coefficient above coefficientMax() counts as zero.
  • < and Decimal.Operation.compare follow IEEE comparison: NaN is .unordered and −0 equals +0. Decimal.Operation.order is the IEEE total order instead: −NaN < −sNaN < −∞ < finite < +∞ < +sNaN < +NaN, −0 precedes +0, and NaNs of the same kind and sign are ordered by payload.
  • Every operation rounds once, to the precision and rounding of its Decimal.Context. fuse computes self × a + b exactly and rounds only the final sum. The operators, integer literals and Swift.FloatingPoint requirements use the format's default context (Decimal.Context.format64 and its siblings: round half to even, no traps) and discard the status.
  • Decimal.Context.traps takes effect only through the trapping: overloads. Each of these throws one Decimal.Trap for the first raised flag in Decimal.Flag.allCases order (invalid, divide, overflow, underflow, inexact). The trap carries the full status and the value that would have been returned. The non-throwing overloads never trap.
  • When an operand is a signaling NaN, the result is a quiet NaN that carries the first signaling operand's coefficient as its payload, and .invalid is raised. Otherwise the first quiet NaN operand is returned unchanged, with no flag.
  • These operations return NaN with .invalid: ∞ − ∞, 0 × ∞, 0 ÷ 0 and ∞ ÷ ∞, and in fuse an infinite product added to an infinity of the opposite sign. Dividing a nonzero finite value by zero returns a signed infinity with .divide.
  • An exact zero sum is +0, unless both operands are −0 or the rounding is .down. Then it is −0.
  • An integer literal rounds half to even when it has more digits than the format's precision. So does init(_:) taking an Int or a generic BinaryInteger, and an integer that exceeds the exponent range becomes infinity. init?(exactly:) returns nil instead of rounding. Every Int64 literal is exact in Decimal.Format128.
  • Decimal.Text.Parse accepts an optional sign, digits with at most one ., and an optional E/e exponent. It also accepts Inf, Infinity and the text "NaN" in any letter case, with an optional sign. Leading zeros do not count toward precision. A coefficient with too many digits is rounded by the context and the parse does not report it as inexact. An exponent outside the context's range throws instead of producing infinity or zero.
  • Rendering writes the text "NaN" and Infinity with their sign, but a NaN's payload and its signaling kind are dropped. Any zero renders as 0 (or -0), whatever its exponent. .plain never uses exponent notation, so it writes every zero digit. .scientific always writes a signed exponent. .engineering writes an exponent that is a multiple of three, or none when that exponent is zero. render(into:) requires a buffer of at least requiredCapacity(style:) bytes.

Package Metadata

Repository: swift-atoms/swift-decimal

Default branch: main

README: README.md