Complete Guide to C# BigInteger: Deep Dive with Examples

The BigInteger type in C# solves a fundamental limitation of fixed-size numeric types like int, long, and even Int128, which are constrained by predefined bit lengths and can easily overflow when handling very large values. These constraints make traditional types unsuitable for scenarios that involve high-precision or unbounded numerical data, such as cryptographic key generation, large-scale scientific simulations, blockchain computations, and certain financial calculations involving massive integer ranges. BigInteger addresses this by providing an arbitrarily large integer representation that automatically scales to accommodate the size of the number, bounded only by the system’s memory. It is immutable, supports a wide range of arithmetic and bitwise operations, and integrates with .NET’s type system through various interfaces. This flexibility allows developers to work with large numbers safely and efficiently, without resorting to error-prone custom implementations or external libraries.


Table of Contents

  1. What is BigInteger?
  2. Namespaces and Assembly
  3. Constructors
  4. Key Properties
  5. Methods
  6. Operators
  7. Interfaces Implemented
  8. Using Interfaces with BigInteger
  9. Practical Examples
  10. Performance Considerations
  11. Custom Structs Based on BigInteger

1. What is BigInteger?

BigInteger is an immutable type that represents a whole number with arbitrary precision. It grows in size dynamically to accommodate any integer value, regardless of how many digits it contains.

BigInteger big = BigInteger.Parse("123456789123456789123456789123456789");

2. Namespaces and Assembly

To use BigInteger, you need to include the following:

using System.Numerics;

Ensure your project references the System.Numerics assembly. This is built-in in .NET Core and .NET 5+, but you may need to add it manually for older projects.

3. Constructors

You can create BigInteger instances in several ways:

BigInteger a = new BigInteger(12345); // From int 
BigInteger b = BigInteger.Parse("9876543210123456789"); // From string 
BigInteger c = new BigInteger(new byte[] { 1, 0, 0, 0 }); // From byte array

4. Key Properties

  • IsZero – Returns true if the value is 0
  • IsOne – Returns true if the value is 1
  • IsEven – Returns true if the number is even
  • Sign – Returns -1 (negative), 0 (zero), or 1 (positive)
BigInteger num = new BigInteger(-42); 
Console.WriteLine(num.Sign); // Output: -1

5. Methods

  • Parse(string) – Parses a string to BigInteger
  • TryParse(string, out BigInteger) – Safely parses string
  • ToByteArray() – Converts BigInteger to byte array
  • Abs(BigInteger) – Absolute value
  • Pow(BigInteger, int) – Exponentiation
  • GreatestCommonDivisor(BigInteger, BigInteger)
using System;
using System.Numerics;

class Program
{
    static void Main()
    {
        BigInteger parsed = BigInteger.Parse("123456789012345678901234567890");
        Console.WriteLine($"Parsed: {parsed}");

        bool success = BigInteger.TryParse("98765432109876543210", out BigInteger tryParsed);
        Console.WriteLine($"TryParsed Success: {success}, Value: {tryParsed}");

        byte[] bytes = parsed.ToByteArray();
        BigInteger fromBytes = new BigInteger(bytes);
        Console.WriteLine($"Restored from bytes: {fromBytes}");

        BigInteger absolute = BigInteger.Abs(new BigInteger(-123456));
        Console.WriteLine($"Absolute: {absolute}");

        BigInteger power = BigInteger.Pow(2, 10);
        Console.WriteLine($"2^10: {power}");

        BigInteger gcd = BigInteger.GreatestCommonDivisor(48, 18);
        Console.WriteLine($"GCD of 48 and 18: {gcd}");
    }
}

6. Operators

BigInteger overloads all standard arithmetic and comparison operators:

BigInteger a = 999999999; 
BigInteger b = 888888888;

BigInteger sum = a + b; 
BigInteger product = a * b; 
bool isEqual = a == b;

7. Interfaces Implemented

BigInteger implements several interfaces:

  • IComparable
  • IComparable<BigInteger>
  • IEquatable<BigInteger>
  • IFormattable
  • ISpanFormattable
  • IConvertible
  • IBinaryInteger<BigInteger> (.NET 7+)
  • INumber<BigInteger> (.NET 7+)

These interfaces enable sorting, equality comparison, formatting, and integration with generic math APIs.

8. Using Interfaces with BigInteger

IComparable / IComparable

Allows comparison and sorting:

List<BigInteger> numbers = new List<BigInteger> { 5, 1000, 50 }; 
numbers.Sort();

IEquatable

Enables equality checks:

BigInteger a = 123;
BigInteger b = 123;
Console.WriteLine(a.Equals(b)); // True

IFormattable / ISpanFormattable

For string formatting:

BigInteger big = BigInteger.Pow(2, 100);
Console.WriteLine(big.ToString("N0")); // Formatted with commas

IConvertible

Allows conversion to other types:

int converted = ((IConvertible)big).ToInt32(null);

IBinaryInteger and INumber (in .NET 7+)

Used for generic math APIs:

T Square<T>(T value) where T : IBinaryInteger<T> => value * value;

9. Practical Examples

Check if Value Fits in 256-bit

BigInteger value = BigInteger.Parse("115792089237316195423570985008687907853269984665640564039457584007913129639939");
BigInteger max256 = BigInteger.Pow(2, 256) - 1;

if (value > max256)
    Console.WriteLine("Too big for 256-bit!");

Convert to and from Byte Array

BigInteger number = new BigInteger(1234567890);
byte[] bytes = number.ToByteArray();
BigInteger restored = new BigInteger(bytes);

10. Performance Considerations

  • Slower than primitive types due to dynamic memory and big number math
  • Best used only when necessary (e.g., when numbers exceed long/Int128)
  • Use caching or optimized algorithms for performance-critical tasks

11. Custom Structs Based on BigInteger

You can wrap BigInteger in a struct to enforce bit-size limits, such as a UInt256 type:

public struct UInt256
{
    private BigInteger _value;
    private static readonly BigInteger Max = BigInteger.Pow(2, 256) - 1;

    public UInt256(BigInteger value)
    {
        if (value < 0 || value > Max)
            throw new ArgumentOutOfRangeException();
        _value = value;
    }

    public static implicit operator BigInteger(UInt256 u) => u._value;
    public static explicit operator UInt256(BigInteger b) => new UInt256(b);
    public override string ToString() => _value.ToString();
}

Conclusion

BigInteger is a powerful type for working with huge whole numbers in C#. It provides a rich set of operators, methods, and interfaces, making it flexible for a variety of advanced scenarios. With .NET 7 introducing even more generic math capabilities, BigInteger now plays nicely in modern C# numerical code. Use it wisely where precision and size matter more than performance.