Skip to content

Repository files navigation

ktsu.PreciseNumber

A high-precision numeric type for .NET that provides arbitrary precision arithmetic with a focus on accuracy. By combining the scale benefits of scientific notation with the precision of BigInteger, this library offers reliable and accurate mathematical operations where standard floating point types fall short.

LicenseNuGet VersionNuGet VersionNuGet DownloadsGitHub commit activityGitHub contributorsGitHub Actions Workflow Status

Table of Contents

Features

  • Arbitrary Precision: Based on BigInteger for the significand, allowing numbers of unlimited size.

  • Scientific Notation: Uses an exponent and significand (the coefficient or mantissa in scientific notation) model similar to scientific notation.

  • Lossless Arithmetic: Preserves precision during calculations with no rounding errors.

  • Full .NET Integration: Implements INumber<T> interface for seamless integration with .NET's numeric ecosystem.

  • Comprehensive Mathematical Support: Includes advanced mathematical functions like exponential operations (Pow, Exp, Squared, Cubed), constant values (Pi, E, Tau) with high precision, absolute value operations, and specialized numerical checks (isOdd, isEven, etc.)—all with arbitrary precision.

  • Balanced Performance: The design prioritizes accuracy and precision while maintaining reasonable performance. For calculations where extreme precision matters more than raw speed, PreciseNumber delivers excellent results, though built-in numeric types remain faster for standard precision needs.

Getting Started

Installation

To install PreciseNumber, you can use the .NET CLI:

dotnet add package ktsu.PreciseNumber 

Or you can use the NuGet Package Manager in Visual Studio by searching for ktsu.PreciseNumber.

Requirements

This library requires .NET 8.0 or later.

Quick Usage

Basic Example

usingSystem.Numerics;usingktsu.PreciseNumber;// Create PreciseNumber from various types varprecise1=123.456.ToPreciseNumber();varprecise2=BigInteger.Parse("1234567890").ToPreciseNumber();// Perform calculation with high precision varresult=precise1*precise2/7.89.ToPreciseNumber();Console.WriteLine(result);// Displays accurate result with no floating point errors 

Common Operations

Create and perform operations with precise numbers:

usingktsu.PreciseNumber;// Create PreciseNumbers from various numeric types vara=123.456.ToPreciseNumber();varb=2.ToPreciseNumber();// Basic arithmetic operations varsum=a+b;// 125.456 vardifference=a-b;// 121.456 varproduct=a*b;// 246.912 varquotient=a/b;// 61.728 // Comparison boolisGreater=a>b;// true 

When to Use PreciseNumber

PreciseNumber is ideal for:

  • Financial calculations where exact precision is required beyond what decimal offers

  • Scientific computing involving very large or small numbers with many significant digits

  • Cryptography applications requiring arbitrary precision arithmetic

  • Mathematical algorithms where rounding errors would accumulate and affect results

For everyday calculations where standard precision is sufficient, built-in types like int, double, or decimal will offer better performance.

Advanced Usage

Type Conversions

The library provides seamless round-trip conversions between standard numeric types and PreciseNumber using extension methods:

usingSystem.Numerics;usingktsu.PreciseNumber;// Convert FROM standard types TO PreciseNumber intoriginalInt=42;doubleoriginalDouble=3.14159;decimaloriginalDecimal=1234.5678m;BigIntegeroriginalBigInt=BigInteger.Parse("123456789012345678901234567890");// Convert using the ToPreciseNumber() extension method varpreciseInt=originalInt.ToPreciseNumber();varpreciseDouble=originalDouble.ToPreciseNumber();varpreciseDecimal=originalDecimal.ToPreciseNumber();varpreciseBigInt=originalBigInt.ToPreciseNumber();// Perform precise calculations if needed preciseInt*=10;preciseDouble+=PreciseNumber.Pi;// Convert back FROM PreciseNumber TO standard types using To<T>() introundTripInt=preciseInt.To<int>();// 420 doubleroundTripDouble=preciseDouble.To<double>();// ~6.28318 decimalroundTripDecimal=preciseDecimal.To<decimal>();// 1234.5678 BigIntegerroundTripBigInt=preciseBigInt.To<BigInteger>();// 123456789012345678901234567890 // Verify round-trip conversion (for values that weren't modified) Console.WriteLine(originalDecimal==roundTripDecimal);// True Console.WriteLine(originalBigInt==roundTripBigInt);// True 

Mathematical Functions

PreciseNumber supports a wide range of mathematical operations:

usingktsu.PreciseNumber;varnumber=2.5.ToPreciseNumber();// Exponentiation varsquared=number.Squared();// 6.25 varcubed=number.Cubed();// 15.625 vartoThe4th=number.Pow(4.ToPreciseNumber());// 39.0625 // Constants varpi=PreciseNumber.Pi;vare=PreciseNumber.E;// Exponential function varexpValue=PreciseNumber.Exp(1.ToPreciseNumber());// e^1 = e // Rounding and precision control varroundedValue=number.Round(1);// 2.5 (already at 1 decimal place) varreducedValue=number.ReduceSignificance(1);// 3 (reduced to 1 significant digit) // Min, Max, Abs, and Clamp varabsValue=(-5).ToPreciseNumber().Abs();// 5 varmaxValue=PreciseNumber.Max(2.ToPreciseNumber(),3.ToPreciseNumber());// 3 varminValue=PreciseNumber.Min(2.ToPreciseNumber(),3.ToPreciseNumber());// 2 varclampedValue=10.ToPreciseNumber().Clamp(0,5);// 5 (clamped to maximum) 

Parsing and Formatting

Parsing from Strings

usingSystem.Globalization;usingSystem.Numerics;usingktsu.PreciseNumber;// Parse from string using various formats varnumber1=PreciseNumber.Parse("123.456",CultureInfo.InvariantCulture);varnumber2=PreciseNumber.Parse("1.23E4",NumberStyles.Any,CultureInfo.InvariantCulture);// Try parsing with error handling if(PreciseNumber.TryParse("456.789",outvarresult)){Console.WriteLine($"Parsed successfully: {result}");}

String Formatting

Convert PreciseNumber to string:

usingktsu.PreciseNumber;varnumber=123.456.ToPreciseNumber();stringformatted=number.ToString();// "123.456" 

Comparison with Built-in Types

PreciseNumber vs. double/float

  • Advantages of PreciseNumber:*
  • No Rounding Errors: Unlike floating-point types, PreciseNumber doesn't suffer from binary representation issues (e.g., 0.1 + 0.2 ≠ 0.3 in floating point)

  • Arbitrary Precision: Not limited to 15-17 significant digits (double) or 6-9 significant digits (float)

  • Consistent Results: Mathematical operations produce identical results regardless of magnitude

  • No Special Values: PreciseNumber doesn't have NaN or Infinity values that can propagate through calculations

// Double arithmetic issue doublea=0.1;doubleb=0.2;Console.WriteLine(a+b==0.3);// False (equals 0.30000000000000004) // PreciseNumber solves this varpa=0.1.ToPreciseNumber();varpb=0.2.ToPreciseNumber();Console.WriteLine((pa+pb)==0.3.ToPreciseNumber());// True (exactly 0.3) 

PreciseNumber vs. decimal

  • Advantages of PreciseNumber:*
  • Unlimited Range: Not constrained by decimal's ±7.9E±28 range

  • Unlimited Precision: Decimal is limited to 28-29 significant digits

  • Scientific Operations: Better suited for scientific calculations requiring extreme precision

  • More Flexible Format: Exponent-significand model makes it suitable for both very large and very small numbers

// Decimal range/precision limitations decimallargeDecimal=1.0m;for(inti=0;i<30;i++)largeDecimal*=10;// Will throw OverflowException // PreciseNumber handles this easily varlargePrecise=PreciseNumber.One;for(inti=0;i<1000;i++)largePrecise*=10;// Works fine with arbitrary large values 

PreciseNumber vs. BigInteger

  • Advantages of PreciseNumber:*
  • Decimal Point Support: Represents both integer and fractional parts while BigInteger only handles integers

  • Scientific Notation: More convenient for very large or small numbers with fraction components

  • Mathematical Constants: Built-in support for constants like Pi and E with high precision

Technical Details

Internal Representation

PreciseNumber stores values in the form: significand × 10^exponent

  • Significand: A BigInteger that contains all the significant digits

  • Exponent: An int that determines the decimal place

This representation allows for:

  • Exact representation of integers of any size

  • High precision for decimal values

  • Accurate arithmetic without floating-point errors

Precision Control

You can control precision using:

  • Round(): Rounds to a specific number of decimal places

  • ReduceSignificance(): Reduces to a specific number of significant digits

Limitations

  • Operations that inherently require approximation (like certain roots or logarithms) fall back to double precision for calculation

  • Conversion to standard types may throw OverflowException if the value is too large

API Reference

PreciseNumber Class

  • Constants: Zero, One, NegativeOne, Pi, E, Tau

  • Arithmetic: +, -, *, /, %, ++, --

  • Comparison: ==, !=, <, >, <=, >=

  • Functions: Abs(), Round(), Clamp(), Squared(), Cubed(), Pow(), Exp()

  • Utility: ToString(), Parse(), TryParse(), To<T>()

PreciseNumberExtensions Class

  • Conversion: ToPreciseNumber<T>()extension method for anyINumber<T>

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.

Acknowledgements

Thanks to the .NET community and ktsu.dev contributors for their support.

About

A high-precision numeric type for .NET that provides arbitrary precision arithmetic with a focus on accuracy.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages