ktsu.SignificantNumber 2.0.3

Prefix Reserved
dotnet add package ktsu.SignificantNumber --version 2.0.3
                    
NuGet\Install-Package ktsu.SignificantNumber -Version 2.0.3
                    
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="ktsu.SignificantNumber" Version="2.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ktsu.SignificantNumber" Version="2.0.3" />
                    
Directory.Packages.props
<PackageReference Include="ktsu.SignificantNumber" />
                    
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 ktsu.SignificantNumber --version 2.0.3
                    
#r "nuget: ktsu.SignificantNumber, 2.0.3"
                    
#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 ktsu.SignificantNumber@2.0.3
                    
#: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=ktsu.SignificantNumber&version=2.0.3
                    
Install as a Cake Addin
#tool nuget:?package=ktsu.SignificantNumber&version=2.0.3
                    
Install as a Cake Tool

ktsu.SignificantNumber

NuGet Version NuGet Version GitHub commit activity GitHub branch status

License NuGet Version NuGet Version NuGet Downloads GitHub commit activity GitHub contributors GitHub Actions Workflow Status

SignificantNumber is a numeric value type whose arithmetic follows the rules for significant figures. It holds a ktsu.PreciseNumber and rounds every result to the precision its operands justify.

Features

  • Addition and subtraction round to the fewest decimal places among the operands, and multiplication, division, and modulus round to the fewest significant digits
  • Operands of exactly -1, 0, or 1 have unlimited precision, so they never limit a result
  • A readonly record struct whose default is zero, holding a PreciseNumber that it converts to implicitly
  • Implements INumber<SignificantNumber>, including CreateChecked, CreateSaturating, and CreateTruncating for every built-in numeric type, BigInteger, and PreciseNumber

Upgrading from 1.x? See the 2.0 migration guide.

Table of contents

Performance

<picture> <source media="(prefers-color-scheme: dark)" srcset="docs/benchmarks/performance-dark.svg"> <img alt="Allocated bytes per operation, and time relative to a fixed reference workload, for each SignificantNumber release" src="docs/benchmarks/performance.svg"> </picture>

Every release measures a fixed set of benchmarks and adds a point to the chart; the numbers behind it are in docs/benchmarks/history.json, and the suite is SignificantNumber.Benchmarks.

Read the two halves differently. Allocation is exact — the same code allocates the same bytes on any machine, so a step in the top row is always a real change. Time is measured on shared CI runners, where the host a job happens to land on varies more than most releases do, so each time is divided by a reference workload measured in the same job. That cancels most of the difference between machines; what is left is indicative rather than precise.

The step at 2.0 is the type becoming a readonly record struct over PreciseNumber instead of deriving from it. A 200-digit addition went from 54,688 bytes and 128 μs to 112 bytes and 340 ns.

Installation

Install the package with the .NET CLI:

dotnet add package ktsu.SignificantNumber

Or add the package reference directly in your project file:

<PackageReference Include="ktsu.SignificantNumber" Version="x.x.x" />

Usage

Creating a SignificantNumber

Create a SignificantNumber from any supported numeric type with the ToSignificantNumber extension method, from text with Parse, or from a PreciseNumber with an explicit cast.

Supported numeric types

ToSignificantNumber converts through INumber<T>. These types are supported:

  • Integer types:

    • int
    • long
    • short
    • sbyte
    • uint
    • ulong
    • ushort
    • byte
    • BigInteger
  • Floating point types:

    • double
    • float
    • Half
    • decimal
  • ktsu types:

    • PreciseNumber
    • SignificantNumber

Examples

using System.Numerics;
using ktsu.PreciseNumber;
using ktsu.SignificantNumber;

// Integer types
int intValue = 12345;
SignificantNumber significantNumberFromInt = intValue.ToSignificantNumber();

BigInteger bigIntValue = new BigInteger(9876543210);
SignificantNumber significantNumberFromBigInt = bigIntValue.ToSignificantNumber();

// Floating point types
double doubleValue = 123.45;
SignificantNumber significantNumberFromDouble = doubleValue.ToSignificantNumber();

Half halfValue = (Half)123.45;
SignificantNumber significantNumberFromHalf = halfValue.ToSignificantNumber();

float floatValue = 123.45f;
SignificantNumber significantNumberFromFloat = floatValue.ToSignificantNumber();

decimal decimalValue = 123.45m;
SignificantNumber significantNumberFromDecimal = decimalValue.ToSignificantNumber();

// A PreciseNumber, with an explicit cast because it opts into the significant figure rules
PreciseNumber precise = 12.5.ToPreciseNumber();
SignificantNumber significantNumberFromPrecise = (SignificantNumber)precise;

Arithmetic operations

SignificantNumber result1 = number1 + number2;
SignificantNumber result2 = number1 - number2;
SignificantNumber result3 = number1 * number2;
SignificantNumber result4 = number1 / number2;

// Square and cube operations, which return the unrounded PreciseNumber
PreciseNumber squared = number1.Squared();
PreciseNumber cubed = number1.Cubed();

// Power operation
SignificantNumber powerResult = number1.Pow(3.ToPreciseNumber());

The operators also accept a PreciseNumber on either side, and the result is a SignificantNumber.

Comparison operations

bool isEqual = number1 == number2;
bool isGreater = number1 > number2;
bool isLessOrEqual = number1 <= number2;

Ordering operators compare values exactly. SignificantNumber.CompareTo(left, right) and CompareTo(SignificantNumber) compare both numbers at the lower of their significant digit counts.

Formatting and parsing

Format a SignificantNumber as a string:

string formatted = number1.ToString("G", CultureInfo.InvariantCulture);
Console.WriteLine(formatted);  // Outputs the formatted number

Parse one from text, including scientific notation:

SignificantNumber parsed = SignificantNumber.Parse("1.23E4", NumberStyles.Float, CultureInfo.InvariantCulture);

if (SignificantNumber.TryParse("123.45", CultureInfo.InvariantCulture, out SignificantNumber result))
{
    Console.WriteLine(result);
}

TryParse yields zero when parsing fails.

Extension methods

ToSignificantNumber

Converts a supported numeric type to a SignificantNumber. An overload takes the number of significant digits to keep.

Usage
public static SignificantNumber ToSignificantNumber<TInput>(this TInput input)
    where TInput : INumber<TInput>

public static SignificantNumber ToSignificantNumber<TInput>(this TInput input, int significantDigits)
    where TInput : INumber<TInput>
Parameters
  • input: The number to convert.
  • significantDigits: The number of significant digits to keep. It must be greater than zero.
Returns
  • SignificantNumber: The converted number.
Example
double floatingPointValue = 123.45;
SignificantNumber significantNumberFromFloat = floatingPointValue.ToSignificantNumber();

int integerValue = 12345;
SignificantNumber significantNumberFromInt = integerValue.ToSignificantNumber();

SignificantNumber result = significantNumberFromFloat + significantNumberFromInt;
// result = 12468.45

Conversion

To<TOutput>

Converts a SignificantNumber to the specified numeric type.

Usage
public TOutput To<TOutput>()
    where TOutput : INumber<TOutput>
Returns
  • TOutput: The converted value of the SignificantNumber.
Example
SignificantNumber significantNumber = SignificantNumber.Parse("12345E3", NumberStyles.Float, CultureInfo.InvariantCulture);
double result = significantNumber.To<double>();
Console.WriteLine(result);  // Outputs 12345000

Generic code converts the same way through CreateChecked, CreateSaturating, and CreateTruncating:

static T ToMeters<T>(T feet) where T : INumber<T> => feet * T.CreateChecked(0.3048);

SignificantNumber meters = ToMeters(10.ToSignificantNumber());
double asDouble = double.CreateChecked(meters);

A SignificantNumber converts to a PreciseNumber implicitly, and Value returns the PreciseNumber it holds.

Precision

Significand and exponent

A SignificantNumber holds a PreciseNumber, which stores two components:

  • Significand: The significant digits of the number, stored as a BigInteger.
  • Exponent: The power of ten that scales the significand.

Significand, Exponent, and SignificantDigits are available directly on SignificantNumber.

Precision handling

  • Floating point input: A float keeps up to 8 significant digits, and a double up to 16.
  • Trailing zero removal: Trailing zeros move from the significand into the exponent, so every value is stored in its most compact form.
  • Rounding: Round rounds to a number of decimal digits, and ReduceSignificance to a number of significant digits.

Example of precision

Consider the number 123.456000:

  • As a SignificantNumber, it's stored as 123456e-3 after removing the trailing zeros and adjusting the exponent.
  • Adding 1.2 to it rounds the sum to one decimal place, giving 124.7, because 1.2 has the fewest decimal places.

API reference

Properties

  • PreciseNumber Value - Gets the PreciseNumber the number holds.
  • int Exponent, BigInteger Significand, and int SignificantDigits - Get the components of the held value.
  • static SignificantNumber NegativeOne, One, and Zero - Get -1, 1, and 0. Zero is also default.
  • static SignificantNumber E, Pi, and Tau - Get the mathematical constants.
  • static int Radix - Gets the radix, or base, for the type.
  • static SignificantNumber AdditiveIdentity - Gets the additive identity of the type.
  • static SignificantNumber MultiplicativeIdentity - Gets the multiplicative identity of the type.

Methods

  • bool Equals(SignificantNumber other) - Determines whether two numbers have the same significand and exponent.
  • int CompareTo(object? obj) - Compares the current instance with another object.
  • int CompareTo(SignificantNumber other) - Compares the current instance with another significant number at the lower of their significant digit counts.
  • int CompareTo<TInput>(TInput other) where TInput : INumber<TInput> - Compares the value of the current instance with another number.
  • PreciseNumber Abs() - Returns the absolute value of the current instance.
  • PreciseNumber Round(int decimalDigits) - Rounds the current instance to the specified number of decimal digits.
  • PreciseNumber ReduceSignificance(int significantDigits) - Reduces the current instance to the specified number of significant digits.
  • PreciseNumber Clamp<TNumber>(TNumber min, TNumber max) where TNumber : INumber<TNumber> - Clamps the current instance between the minimum and maximum values.
  • SignificantNumber Pow(PreciseNumber power) - Raises the current instance to a power.
  • PreciseNumber ToPreciseNumber() - Returns the PreciseNumber the number holds.
  • string ToString(string? format, IFormatProvider? formatProvider) - Converts the current instance to a string using the specified format and format provider.
  • bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) - Attempts to format the current instance into the provided span.
  • TOutput To<TOutput>() where TOutput : INumber<TOutput> - Converts the current significant number to the specified numeric type.

Static methods

  • static SignificantNumber FromPreciseNumber(PreciseNumber value) - Creates a significant number that holds a PreciseNumber.
  • static SignificantNumber Add, Subtract, Multiply, Divide, and Mod(PreciseNumber left, PreciseNumber right) - Apply the significant figure rules to two numbers.
  • static SignificantNumber Exp(PreciseNumber power) - Raises e to a power.
  • static SignificantNumber Max, Min(SignificantNumber x, SignificantNumber y), and Clamp(SignificantNumber value, SignificantNumber min, SignificantNumber max) - Compare by value.
  • static SignificantNumber Round(SignificantNumber value, int decimalDigits) - Rounds a number to the specified number of decimal digits.
  • static SignificantNumber Abs(SignificantNumber value) - Returns the absolute value of a SignificantNumber.
  • static bool IsCanonical(SignificantNumber value) - Determines whether the specified value is canonical.
  • static bool IsComplexNumber(SignificantNumber value) - Determines whether the specified value is a complex number.
  • static bool IsEvenInteger(SignificantNumber value) - Determines whether the specified value is an even integer.
  • static bool IsFinite(SignificantNumber value) - Determines whether the specified value is finite.
  • static bool IsImaginaryNumber(SignificantNumber value) - Determines whether the specified value is an imaginary number.
  • static bool IsInfinity(SignificantNumber value) - Determines whether the specified value is infinite.
  • static bool IsInteger(SignificantNumber value) - Determines whether the specified value is an integer.
  • static bool IsNaN(SignificantNumber value) - Determines whether the specified value is NaN.
  • static bool IsNegative(SignificantNumber value) - Determines whether the specified value is negative.
  • static bool IsNegativeInfinity(SignificantNumber value) - Determines whether the specified value is negative infinity.
  • static bool IsNormal(SignificantNumber value) - Determines whether the specified value is normal.
  • static bool IsOddInteger(SignificantNumber value) - Determines whether the specified value is an odd integer.
  • static bool IsPositive(SignificantNumber value) - Determines whether the specified value is positive.
  • static bool IsPositiveInfinity(SignificantNumber value) - Determines whether the specified value is positive infinity.
  • static bool IsRealNumber(SignificantNumber value) - Determines whether the specified value is a real number.
  • static bool IsSubnormal(SignificantNumber value) - Determines whether the specified value is subnormal.
  • static bool IsZero(SignificantNumber value) - Determines whether the specified value is zero.
  • static SignificantNumber MaxMagnitude(SignificantNumber x, SignificantNumber y) - Returns the larger of the magnitudes of two significant numbers.
  • static SignificantNumber MaxMagnitudeNumber(SignificantNumber x, SignificantNumber y) - Returns the larger of the magnitudes of two significant numbers.
  • static SignificantNumber MinMagnitude(SignificantNumber x, SignificantNumber y) - Returns the smaller of the magnitudes of two significant numbers.
  • static SignificantNumber MinMagnitudeNumber(SignificantNumber x, SignificantNumber y) - Returns the smaller of the magnitudes of two significant numbers.

Operators

  • static implicit operator PreciseNumber(SignificantNumber value) - Converts to the held PreciseNumber.
  • static explicit operator SignificantNumber(PreciseNumber value) - Creates a significant number that holds a PreciseNumber.
  • static SignificantNumber operator -(SignificantNumber value) - Negates a significant number.
  • static SignificantNumber operator +, -, *, /, and % - Apply the significant figure rules. Each also accepts a PreciseNumber on either side.
  • static SignificantNumber operator +(SignificantNumber value) - Returns the unary plus of a significant number.
  • static SignificantNumber operator ++ and -- - Increment and decrement by one.
  • static bool operator == and != - Determine whether two numbers are equal, including against a PreciseNumber.
  • static bool operator >, <, >=, and <= - Compare two numbers, including against a PreciseNumber.

Contributing

Contributions are welcome. Submit a pull request or open an issue.

License

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

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 is compatible.  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 (1)

Showing the top 1 NuGet packages that depend on ktsu.SignificantNumber:

Package Downloads
ktsu.PhysicalQuantity

Physical Quantity

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.3 0 9/16/2026
2.0.2 28 9/16/2026
2.0.1 53 9/16/2026
2.0.0 80 9/15/2026
1.4.40 89 9/14/2026
1.4.39 89 9/11/2026
1.4.38 115 9/4/2026
1.4.37 109 9/3/2026
1.4.36 106 8/28/2026
1.4.35 107 8/26/2026
1.4.34 116 8/24/2026
1.4.33 112 8/21/2026
1.4.32 104 8/20/2026
1.4.31 108 8/19/2026
1.4.30 105 8/18/2026
1.4.29 110 8/17/2026
1.4.28 97 8/11/2026
1.4.27 104 8/6/2026
1.4.26 94 8/6/2026
1.4.25 100 8/5/2026
Loading failed

## v2.0.3 (patch)

Changes since v2.0.2:

- Seed the abstraction-cost pair across every release [patch] ([@Claude](https://github.com/Claude))
- Measure this type against a bare double, and chart it per release [patch] ([@Claude](https://github.com/Claude))