Skip to content

Number Base Converter — C# source

Convert numbers between binary, octal, decimal and hexadecimal. BigInt-powered, so it handles arbitrarily large values without precision loss.

This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.

// number-base — C# port: arbitrary-precision base conversion (bases 2-36).
using System;
using System.Numerics;
using System.Text;

namespace NumberBase;

/// <summary>Arbitrary-precision base conversion, ported from src/lib/numberBase.ts.</summary>
public static class NumberBase
{
    const string Digits = "0123456789abcdefghijklmnopqrstuvwxyz";

    /// <summary>Map a lowercase character to its value; -1 when not a digit.</summary>
    static int DigitValue(char c) => c switch {
        >= '0' and <= '9' => c - '0',
        >= 'a' and <= 'z' => c - 'a' + 10,
        _ => -1,
    };

    /// <summary>Parse <paramref name="s"/> in <paramref name="base"/> (2-36); null on
    /// invalid input. A radix prefix is stripped only when it agrees with the base.</summary>
    public static BigInteger? ParseBigInt(string s, int @base)
    {
        if (@base is < 2 or > 36) return null;
        s = s.Trim().ToLowerInvariant();
        bool neg = false;
        if (s.StartsWith('-')) { neg = true; s = s[1..]; }
        else if (s.StartsWith('+')) s = s[1..];
        if ((s.StartsWith("0x") && @base == 16) || (s.StartsWith("0b") && @base == 2) ||
            (s.StartsWith("0o") && @base == 8)) s = s[2..];
        if (s.Length == 0) return null;
        BigInteger result = 0, b = @base;
        foreach (char ch in s)
        {
            int d = DigitValue(ch);
            if (d < 0 || d >= @base) return null;
            result = result * b + d; // Horner's method
        }
        return neg ? -result : result;
    }

    /// <summary>Render <paramref name="value"/> in <paramref name="base"/> (2-36);
    /// "" for an unsupported base, matching the TS lib.</summary>
    public static string FormatBigInt(BigInteger value, int @base)
    {
        if (@base is < 2 or > 36) return "";
        if (value.IsZero) return "0";
        bool neg = value.Sign < 0;
        BigInteger v = BigInteger.Abs(value), b = @base;
        var sb = new StringBuilder();
        while (v > 0)
        {
            v = BigInteger.DivRem(v, b, out BigInteger rem); // peel LSD first
            sb.Append(Digits[(int)rem]);
        }
        if (neg) sb.Append('-');
        char[] chars = sb.ToString().ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }

    /// <summary>value(fromBase) -> toBase; null when it does not parse.</summary>
    public static string? ConvertBase(string value, int fromBase, int toBase) =>
        ParseBigInt(value, fromBase) is { } n ? FormatBigInt(n, toBase) : null;
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →