Bodu.Numerics
1.0.0
dotnet add package Bodu.Numerics --version 1.0.0
NuGet\Install-Package Bodu.Numerics -Version 1.0.0
<PackageReference Include="Bodu.Numerics" Version="1.0.0" />
<PackageVersion Include="Bodu.Numerics" Version="1.0.0" />
<PackageReference Include="Bodu.Numerics" />
paket add Bodu.Numerics --version 1.0.0
#r "nuget: Bodu.Numerics, 1.0.0"
#:package Bodu.Numerics@1.0.0
#addin nuget:?package=Bodu.Numerics&version=1.0.0
#tool nuget:?package=Bodu.Numerics&version=1.0.0
Bodu.Numerics
API stability — Stable. The public API surface is committed; breaking changes are reserved for a major-version bump per SemVer.
Numeric value primitives for .NET. The public model is exact rational numbers plus an interval algebra:
Fraction<T>— an immutable, exact-rational value type generic over anyIBinaryInteger<T>backing component.Interval<T>— an immutable connected interval over anyINumber<T>endpoint type, with independent open/closed (and unbounded) endpoints and set algebra.DiscreteInterval<T>— a connected integer-domain interval overIBinaryInteger<T>, with successor/predecessor-aware emptiness and adjacency.IntervalSet<T>— a normalized set of disconnectedInterval<T>pieces, with N-ary union / intersection / difference / complement.IntervalPair<T>/DiscreteIntervalPair<T>— allocation-conscious results of a binary difference / symmetric-difference (zero, one, or two disjoint pieces), each convertible to anIntervalSet<T>.BigDecimal— an immutable arbitrary-precision decimal (aBigIntegerunscaled value plus anintscale), for exact decimal values beyondSystem.Decimal's precision or exponent range.RunningStatistics<T>/RunningQuantile<T>— single-pass, constant-space accumulators over a sample stream: Welford count/min/max/mean/variance with a parallelCombinemerge, and a P² streaming quantile estimator.MovingSum<T>/MovingMinMax<T>— rolling-window companions that report the sum/mean and min/max of the most recent N samples in amortized O(1).
Money, currency, and foreign-exchange types ship in the companion Bodu.Financial package. Keeping them separate means a consumer of just
Fraction<T>does not pull in the ~185-currency ISO 4217 catalogue and FX provider stack.
Installation
dotnet add package Bodu.Numerics
Targets net8.0.
Fraction<T>
Fraction<T> is always held in canonical form — strictly positive denominator, sign carried on the numerator, fully reduced. Arithmetic is exact: intermediate results are evaluated with BigInteger precision and narrowed back to T, throwing OverflowException when a fixed-width component cannot represent the canonical result.
using Bodu.Numerics;
Fraction<int> a = Fraction<int>.Parse("1/3");
Fraction<int> b = Fraction<int>.Parse("1/6");
Fraction<int> sum = a + b; // 1/2 (canonical, fully reduced)
string mixed = (a + 1).ToString("M"); // "1 1/3"
decimal asDecimal = (decimal)sum; // 0.5m
Highlights:
- Arithmetic and comparison operators, named methods (
Add,Negate,Abs,Reciprocal,Pow,Remainder), andGreatestCommonDivisor/LeastCommonMultiple. - Exact conversions to/from
decimalanddouble(FromDecimal/FromDouble), plusAs<TOther>()to retype the backing component. - Continued-fraction expansion (
ToContinuedFraction/FromContinuedFraction) and bounded best-rational approximation (LimitDenominator). - Parsing of integer, ratio, mixed-number, Unicode vulgar-fraction, and percent forms across
string,ReadOnlySpan<char>, and UTF-8 (IParsable,ISpanParsable,IUtf8SpanParsable); formatting with general, mixed (M), Unicode (U), and percent (P) specifiers. - The full generic-math surface —
INumber<Fraction<T>>,INumberBase<Fraction<T>>,ISignedNumber<Fraction<T>>— soFraction<T>composes withINumber<T>-constrained code. - XML serialization (
IXmlSerializable) andSystem.Text.Jsonsupport.
Interval<T>
using Bodu.Numerics;
Interval<int> a = Interval.Closed(1, 5); // [1, 5]
Interval<int> b = Interval.OpenClosed(4, 8); // (4, 8]
bool overlaps = a.Overlaps(b); // true
Interval<int> meet = a.Intersect(b); // (4, 5]
bool joined = a.TryUnion(b, out Interval<int> u); // true -> [1, 8]
bool contains = a.Contains(3); // true
Highlights:
- Independent endpoint inclusivity:
[a, b],(a, b),[a, b),(a, b]. - Factory methods (
Closed,Open,ClosedOpen,OpenClosed,Singleton,Empty) plus a non-genericIntervalhelper that infersT(Interval.Closed(1, 5)). - Set algebra:
Contains(T),Contains(Interval<T>),Overlaps,Intersect, andTryUnion(which succeeds only when the result is a single contiguous interval). IsEmpty,IsDegenerate, andLength. All empty intervals compare equal toEmpty.- ISO 31-11 bracket-notation formatting and parsing (
IFormattable/ISpanFormattable/IUtf8SpanFormattable/IParsable/ISpanParsable). Empty intervals render as the U+2205 EMPTY SET glyph.
When to use Interval<T> vs DiscreteInterval<T>
Use Interval<T> when the endpoints are coordinates in an ordered numeric continuum — even when T is an integer coordinate type — so the values between the bounds matter. Use DiscreteInterval<T> (over IBinaryInteger<T>) when the interval represents the set of integers between its bounds. The distinction is observable:
Interval<int>.Open(1, 2).IsEmpty; // False — the real coordinates between 1 and 2
DiscreteInterval<int>.Open(1, 2).IsEmpty; // True — no integer lies strictly between 1 and 2
DiscreteInterval<T> is integer-only; it is not a general discrete-domain abstraction over DateOnly, char, or enum ranges. Reach for IntervalSet<T> when a set operation can produce a disconnected result.
BigDecimal
BigDecimal is an unbounded decimal: a BigInteger unscaled value paired with a non-negative int scale, so the value is unscaledValue × 10^-scale. It grows to whatever precision a value needs — there is no MinValue/MaxValue and arithmetic never overflows. Add, subtract, and multiply are exact; division computes to a default 50-digit working precision (half-to-even) unless you pass an explicit scale and rounding mode.
using Bodu.Numerics;
BigDecimal a = BigDecimal.Add(0.1m, 0.2m); // 0.3 exactly
BigDecimal b = BigDecimal.Divide(10m, 3m, scale: 2, MidpointRounding.ToEven); // 3.33
BigDecimal big = BigDecimal.Parse("123456789012345678901234567890.123456789",
System.Globalization.CultureInfo.InvariantCulture);
Highlights:
- Exact
Add/Subtract/Multiply/Negate/Abs/Pow;Dividewith a default precision or an explicit scale andMidpointRounding;Remainder. - Value-based equality and ordering (
1.0equals1.00), scale-preserving formatting until youRound/Floor/Ceiling/Truncate. - Implicit lifts from
int,long,BigInteger, anddecimal; explicit conversions to/fromdoubleand toBigInteger/decimal. - Parsing of plain and scientific decimal text across
string,ReadOnlySpan<char>, and UTF-8;GandFformatting throughIFormattable/ISpanFormattable/IUtf8SpanFormattable. - The full generic-math surface —
INumber<BigDecimal>,ISignedNumber<BigDecimal>(Radix10) — so it composes withINumber<T>-constrained code.
Running and moving statistics
The statistics aggregates summarize a sample stream in one forward pass without storing it. RunningStatistics<T> (Welford) and RunningQuantile<T> (the P² algorithm) are mutable struct accumulators over the whole stream; MovingSum<T> and MovingMinMax<T> are class-based rolling windows over the most recent N samples. All four accept any INumber<T> sample type: extrema and window sums stay exact in T, while means, variances, and quantile estimates are computed in double.
using Bodu.Numerics;
var stats = new RunningStatistics<double>();
var p95 = new RunningQuantile<double>(0.95);
var window = new MovingMinMax<double>(60);
foreach (var latency in latencies)
{
stats.Add(latency);
p95.Add(latency);
window.Add(latency);
}
// stats.Mean, stats.SampleStandardDeviation, stats.Minimum, stats.Maximum
// p95.Estimate — streaming 95th-percentile estimate
// window.Minimum, window.Maximum — extrema of the last 60 samples
Highlights:
- O(1) per sample and constant space; the samples themselves are never stored (the moving types buffer at most one window).
RunningStatistics<T>.Combinemerges independently filled accumulators losslessly (Chan et al.), so streams can be partitioned and accumulated in parallel; P² estimators are deliberately not mergeable.- Non-finite samples (NaN, ±∞) are rejected at
Add, so an estimate can never be silently poisoned, and the rolling-sum arithmetic is checked — fixed-width integer overflow throws instead of silently wrapping. - The running accumulators are mutable value types: copying one snapshots it, which is also the supported checkpoint mechanism — see the guide for the usage rules.
- No JSON converters are provided for the accumulators: their state is transient in-process progress, not a wire contract.
Documentation
See the Bodu.Numerics guide, including the dedicated Interval<T> article.
License
MIT. © Bodu Pty. Ltd.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Bodu.Numerics:
| Package | Downloads |
|---|---|
|
Bodu.Financial
Financial primitives for .NET. Provides Money (runtime-tagged primary monetary type), Money<TCurrency> (opt-in type-parameter currency safety with implicit conversion to and explicit conversion from the runtime form), MoneyBag (mixed-currency portfolios), CurrencyInfo and CurrencyCode (canonical metadata and source-generated active ISO 4217 enum), CurrencyRegistry (runtime lookup including historic currencies), and a foreign-exchange provider stack with both runtime ExchangeRate and typed ExchangeRate<TBase, TQuote>. Ships the full active + historic ISO 4217 catalogue, cash rounding (CHF/AUD/CAD/NZD/SEK/NOK), and an exact-arithmetic escape hatch through Fraction<BigInteger> from Bodu.Numerics. |
|
|
Bodu.Numerics.Serialization.Json
System.Text.Json integration for Bodu.Numerics. Provides converters, a shared serialization policy, and the AddNumericsJsonConverters() registration helper for Fraction<T>, BigDecimal, Complex<T>, Interval<T>, DiscreteInterval<T>, and IntervalSet<T>. The IntervalPair<T> and DiscreteIntervalPair<T> result types are transient and are not serialized; convert them with ToIntervalSet() first. Keeping JSON support in this companion package leaves the core Bodu.Numerics library serialization-agnostic. |
GitHub repositories
This package is not used by any popular GitHub repositories.