Getting Started with BigFloat
Learn how to install and start using BigFloat in your C# projects
Requirements
Run through this short checklist before installing so you do not chase environment issues later.
.NET 9 SDK
BigFloat targets net9.0 in the library project file.
Recent C# compiler
Use the SDK-installed compiler (C# 13 as of .NET 9) for best results.
System.Numerics
BigInteger ships with .NET and powers the mantissa.
Check your toolchain
Run dotnet --list-sdks and confirm a 9.x entry is present before building. If you see only 8.x, install the .NET 9 SDK first.
Installation
Method 1: NuGet Package (Recommended)
The easiest way to add BigFloat to your project is via NuGet (current release: 4.0.0):
Using Package Manager Console:
Install-Package BigFloatLibrary
Using .NET CLI:
dotnet add package BigFloatLibrary
Using PackageReference in .csproj:
<PackageReference Include="BigFloatLibrary" Version="*" />
Use the wildcard when you want to pick up patch updates automatically; pin to 4.0.0 for reproducible builds.
Method 2: Source Code
For maximum control or to contribute to development:
Clone the repository:
git clone https://github.com/SunsetQuest/BigFloat.git
Add to your project:
- Copy the
BigFloatLibraryfolder to your solution - Add a project reference in your .csproj file
- Optional: Include
Constants.csfor mathematical constants
🔍 Verify your clone
From the repo root, run dotnet restore followed by dotnet build BigFloat.sln. This ensures your environment can build the library and run the bundled tests.
Your First BigFloat Program
Let's create a simple program that demonstrates BigFloat's precision advantages and the updated rounding helpers:
dotnet new console -n BigFloatDemo
cd BigFloatDemo
dotnet add package BigFloatLibrary
dotnet run
The dotnet new template defaults to net9.0 when the .NET 9 SDK is installed. If it falls back to net8.0, install the latest SDK and rerun the commands.
using System;
using BigFloatLibrary;
class Program
{
static void Main()
{
// Problem: 0.1 + 0.2 != 0.3 in standard floating point
double d1 = 0.1;
double d2 = 0.2;
double d3 = d1 + d2;
Console.WriteLine($"Double: {d1} + {d2} = {d3}");
Console.WriteLine($"Is 0.1 + 0.2 == 0.3? {d3 == 0.3}"); // False!
// Solution: BigFloat maintains precision
BigFloat b1 = new("0.1");
BigFloat b2 = new("0.2");
BigFloat b3 = b1 + b2;
Console.WriteLine($"\nBigFloat: {b1} + {b2} = {b3}");
Console.WriteLine($"Is 0.1 + 0.2 == 0.3? {b3 == new BigFloat(\"0.3\")}"); // True!
// High precision calculation
BigFloat pi = Constants.Fundamental.Pi;
BigFloat radius = new("10.123456789");
BigFloat area = pi * radius * radius;
Console.WriteLine($"\nCircle area with radius {radius}:");
Console.WriteLine($"Area = {area}");
// Guard-bit–aware rounding (new in 2025)
Console.WriteLine($"Nearest integer: {BigFloat.ToNearestInt(area)}");
}
}
Expected Output:
Double: 0.1 + 0.2 = 0.30000000000000004
Is 0.1 + 0.2 == 0.3? False
BigFloat: 0.1 + 0.2 = 0.3
Is 0.1 + 0.2 == 0.3? True
Circle area with radius 10.123456789:
Area = 321.7526058894951
Nearest integer: 322
Basic Operations
Creating BigFloat Values
// From string (most precise)
BigFloat a = new("123.456789012345678901234567890");
// From double
BigFloat b = new(3.14159265358979323846);
// From integer
BigFloat c = new(42);
// From BigInteger
BigInteger bigInt = BigInteger.Parse("123456789012345678901234567890");
BigFloat d = new(bigInt);
// With specific precision
BigFloat e = BigFloat.IntWithAccuracy(10, 100); // 10 with 100 bits precision
Arithmetic Operations
BigFloat x = new("100.5");
BigFloat y = new("25.25");
// Basic arithmetic
BigFloat sum = x + y; // 125.75
BigFloat diff = x - y; // 75.25
BigFloat prod = x * y; // 2537.625
BigFloat quot = x / y; // 3.98...
BigFloat rem = x % y; // 0.5
// Unary operations
BigFloat neg = -x; // -100.5
BigFloat abs = BigFloat.Abs(x); // 100.5
Comparisons
BigFloat a = new("100.1");
BigFloat b = new("100.2");
// Comparison operators
bool isEqual = a == b; // false
bool isNotEqual = a != b; // true
bool isLess = a < b; // true
bool isGreater = a > b; // false
bool isLessOrEqual = a <= b; // true
bool isGreaterOrEqual = a >= b; // false
// CompareTo method
int comparison = a.CompareTo(b); // -1 (a < b)
Type Conversions
BigFloat bf = new("123.456");
// Check if fits in standard type
if (bf.FitsInADouble())
{
double d = (double)bf;
}
// Explicit conversions
int intValue = (int)bf; // 123 (truncates)
long longValue = (long)bf; // 123
decimal decValue = (decimal)bf; // 123.456
// To string with format
string str1 = bf.ToString(); // "123.456"
string str2 = bf.ToString("E"); // "1.23456E+2"
string str3 = bf.ToString("X"); // Hexadecimal
Understanding Precision
🔍 Key Concept: Guard Bits
BigFloat maintains 32 "guard bits" as hidden extra precision. These bits help maintain accuracy through chains of operations, preventing cumulative rounding errors.
You can see guard bits in action by formatting values that exceed the chosen precision—the trailing X characters indicate rounded-out digits.
Precision in Action
// When you see output like "232XXXXXXXX", the X's indicate out-of-precision digits
BigFloat large = new("232000000000");
Console.WriteLine(large); // May display as "232XXXXXXXX" or "2.32e+11"
// Parsing with precision separator
// Format: "precise_part|guard_bits"
BigFloat precise = BigFloat.Parse("123.456|789");
Console.WriteLine($"Value: {precise}");
// Setting specific precision
BigFloat original = new("3.14159265358979323846264338327950288");
BigFloat rounded = BigFloat.SetPrecisionWithRound(original, 100); // 100 bits
// Extending precision (adds zeros, doesn't add information)
BigFloat extended = BigFloat.ExtendPrecision(original, 50);
⚠️ Important: Base-2 vs Base-10
BigFloat uses binary (base-2) internally. Most decimal numbers cannot be represented exactly in binary, leading to small precision differences:
0.1in decimal =0.00011001100110011...(repeating) in binary0.25in decimal =0.01(exact) in binary
📏 Constructor precision rule
All numeric constructors now follow the same split between in-precision bits and guard bits:
- In-precision first: Take the requested
binaryPrecisionbits, clamped so no more than 32 source bits land in the guard region (fordouble, this enforces at least 21 in-precision bits). - Guard mapping: Any remaining source bits (up to 32) occupy the most significant guard bits; unused guard bits are zero.
- Scaling and zeroes:
binaryScalersimply shiftsScale/BinaryExponent. Zero inputs keep_sizeat 0 and encode the requested precision inScale.
Defaults: double keeps 37 in-precision bits + 16 guard bits from the IEEE payload; float keeps 16 + 8; integers default to 31/63/64 in-precision bits (auto-widening to cover the full payload when it exceeds the default) with remaining guard bits zeroed; decimal adds 96 extra in-precision bits atop its 96-bit mantissa.
Accuracy Controls (New in 2025)
Precision-management APIs were refreshed in the 2025 releases. Prefer these helpers over the
older ExtendPrecision/ReducePrecision calls (still present for backward compatibility):
Grow or shrink accuracy
BigFloat x = new("123.456");
// Add 64 working bits without changing the value
BigFloat wider = BigFloat.AdjustAccuracy(x, +64);
// Remove 32 bits and round before dropping them
BigFloat trimmed = BigFloat.AdjustPrecision(x, -32);
// Set an exact accuracy target (Scale + Precision)
BigFloat target = BigFloat.SetAccuracy(x, 256);
Console.WriteLine(target.Size); // includes 32 guard bits
Rounding and truncation
BigFloat value = new("9876.54321");
// Round to nearest whole number ignoring guard bits
int nearest = BigFloat.ToNearestInt(value);
// Preserve accuracy metadata when forcing an integer
BigFloat integer = value.TruncateToIntegerKeepingAccuracy();
// Reduce size with rounding at the cut point
BigFloat rounded = BigFloat.SetPrecisionWithRound(value, 80);
Parsing with precision hints
// "guard" bits after the pipe are interpreted as accuracy hints
BigFloat parsed = BigFloat.Parse("123.456|789");
Console.WriteLine(parsed.Scale); // radix-point offset
Console.WriteLine(parsed.Size); // mantissa + guard bits
Next Steps
Need Help?
If you run into issues or have questions:
- Check the documentation for detailed information
- Browse GitHub issues for similar problems
- Join the discussion in the community section