Bodu.Numerics 1.0.0

dotnet add package Bodu.Numerics --version 1.0.0
                    
NuGet\Install-Package Bodu.Numerics -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bodu.Numerics" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bodu.Numerics" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Bodu.Numerics" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bodu.Numerics --version 1.0.0
                    
#r "nuget: Bodu.Numerics, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bodu.Numerics@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bodu.Numerics&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Bodu.Numerics&version=1.0.0
                    
Install as a Cake Tool

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 any IBinaryInteger<T> backing component.
  • Interval<T> — an immutable connected interval over any INumber<T> endpoint type, with independent open/closed (and unbounded) endpoints and set algebra.
  • DiscreteInterval<T> — a connected integer-domain interval over IBinaryInteger<T>, with successor/predecessor-aware emptiness and adjacency.
  • IntervalSet<T> — a normalized set of disconnected Interval<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 an IntervalSet<T>.
  • BigDecimal — an immutable arbitrary-precision decimal (a BigInteger unscaled value plus an int scale), for exact decimal values beyond System.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 parallel Combine merge, 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), and GreatestCommonDivisor / LeastCommonMultiple.
  • Exact conversions to/from decimal and double (FromDecimal / FromDouble), plus As<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>> — so Fraction<T> composes with INumber<T>-constrained code.
  • XML serialization (IXmlSerializable) and System.Text.Json support.

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-generic Interval helper that infers T (Interval.Closed(1, 5)).
  • Set algebra: Contains(T), Contains(Interval<T>), Overlaps, Intersect, and TryUnion (which succeeds only when the result is a single contiguous interval).
  • IsEmpty, IsDegenerate, and Length. All empty intervals compare equal to Empty.
  • 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; Divide with a default precision or an explicit scale and MidpointRounding; Remainder.
  • Value-based equality and ordering (1.0 equals 1.00), scale-preserving formatting until you Round / Floor / Ceiling / Truncate.
  • Implicit lifts from int, long, BigInteger, and decimal; explicit conversions to/from double and to BigInteger / decimal.
  • Parsing of plain and scientific decimal text across string, ReadOnlySpan<char>, and UTF-8; G and F formatting through IFormattable / ISpanFormattable / IUtf8SpanFormattable.
  • The full generic-math surface — INumber<BigDecimal>, ISignedNumber<BigDecimal> (Radix 10) — so it composes with INumber<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>.Combine merges 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.

Version Downloads Last Updated
1.0.0 140 9/24/2026
0.7.0 222 9/24/2026
0.6.0 78 9/24/2026
0.5.0 68 9/23/2026