agdgb.NumberFormatter
1.1.0
This package has been officially rebranded and succeeded by 'HumanNumbers.AspNetCore'.
To continue receiving active updates, performance enhancements (including pre-cached O(1) formatting and thread-safe options configuration), and modern ASP.NET Core integrations (TagHelpers, JSON converters, and Minimal API support), please migrate your project references to 'HumanNumbers' (and 'HumanNumbers.AspNetCore' for web applications).
Thank you for your support!
dotnet add package agdgb.NumberFormatter --version 1.1.0
NuGet\Install-Package agdgb.NumberFormatter -Version 1.1.0
<PackageReference Include="agdgb.NumberFormatter" Version="1.1.0" />
<PackageVersion Include="agdgb.NumberFormatter" Version="1.1.0" />
<PackageReference Include="agdgb.NumberFormatter" />
paket add agdgb.NumberFormatter --version 1.1.0
#r "nuget: agdgb.NumberFormatter, 1.1.0"
#:package agdgb.NumberFormatter@1.1.0
#addin nuget:?package=agdgb.NumberFormatter&version=1.1.0
#tool nuget:?package=agdgb.NumberFormatter&version=1.1.0
NumberFormatter
A powerful .NET library for formatting numbers into short, human-readable strings with support for suffixes (K, M, B, T, Qa, Qi), currency symbols, and culture-aware formatting. Includes ASP.NET Core integration for JSON serialization, Razor Tag Helpers, and view components.
Features
- Short number formatting – Convert numbers like
1,234,567into1.23M - Parsing support – Parse formatted strings safely back to numbers without Regex
- Currency support – Display currency symbols with suffix logic (
$1.23M,€987.65K) - Culture-aware – Respects decimal separators and formatting rules of the specified culture
- Digital byte sizes – Format numbers as digital storage (e.g.,
MB,MiB,GB) - Roman numerals – Convert integers to Roman numeral strings
- Basis Points (BPS) – Parse and format financial spreads (
125 bps↔0.0125) - Fractional Prices – Support for Treasury market fractions (
101 16/32↔101.5) - Spelled-out numbers – Convert decimals to words for check writing (
"One Hundred and 50/100") - Customizable suffixes – Use your own suffixes (e.g., "Thousand", "Million", "Lac", "Crore")
- Flexible options – Control decimal places, plus sign, negative patterns, and more
- High performance – Caches formatting options, uses zero-allocation span parsers and efficient logic
- ASP.NET Core integration – JSON converters, DI service, Tag Helper, View Component, and MVC/Razor Pages extensions
- Round-trip JSON – Serialize and deserialize formatted numbers directly securely
- Financial Hardening – Recursive attribute mapping for
decimal?,List<decimal>, andDictionary<string, decimal>
Installation
Core Library
dotnet add package agdgb.NumberFormatter
ASP.NET Core Integration
dotnet add package agdgb.NumberFormatter.AspNetCore
Usage
Basic Number Formatting
using NumberFormatter;
decimal value = 1234567.89m;
Console.WriteLine(value.ToShortString()); // "1.23M"
Console.WriteLine(value.ToShortString(3)); // "1.235M"
int count = 1500;
Console.WriteLine(count.ToShortString()); // "1.50K"
Currency Formatting
decimal amount = 987654.32m;
// Using current culture's currency symbol
Console.WriteLine(amount.ToShortCurrencyString()); // "$987.65K"
// Specifying a currency code
Console.WriteLine(amount.ToShortCurrencyString("EUR")); // "€987.65K"
// Using a custom currency symbol
var options = new ShortNumberFormatOptions
{
CurrencySymbol = "¥",
CurrencyPosition = CurrencyPosition.After
};
Console.WriteLine(amount.ToShortString(options)); // "987.65K¥"
Custom Options
var options = new ShortNumberFormatOptions
{
DecimalPlaces = 1,
ShowPlusSign = true,
NegativePattern = "(n)",
CustomSuffixes = new[] { "", "Thousand", "Million", "Billion" }
};
Console.WriteLine(1234.56m.ToShortString(options)); // "+1.2Thousand"
Console.WriteLine((-1234.56m).ToShortString(options)); // "(1.2Thousand)"
Culture-Aware Formatting
using System.Globalization;
var germanCulture = new CultureInfo("de-DE");
Console.WriteLine(1234.56m.ToShortString(2, germanCulture)); // "1,23K"
Working with Different Numeric Types
The library supports any type implementing INumber<T>, including int, long, double, and float.
long bigNumber = 1234567890123L;
Console.WriteLine(bigNumber.ToShortString()); // "1.23T"
Parsing Short Numbers
You can parse formatted short strings back into numeric values using TryParse and Parse. This safely strips currency symbols and understands suffixes.
if (NumberFormatter.TryParse("$1.5M", out decimal result))
{
Console.WriteLine(result); // 1500000
}
decimal value = NumberFormatter.Parse("50K"); // 50000
Byte Size Formatting
Format digital storage sizes with ToShortByteString. Supports both binary (base-1024, e.g. MiB) and decimal (base-1000, e.g. MB) prefixes.
long memory = 1536 * 1024;
Console.WriteLine(memory.ToShortByteString(decimalPlaces: 2, useBinaryPrefixes: true)); // "1.50 MiB"
Console.WriteLine(memory.ToShortByteString(decimalPlaces: 2, useBinaryPrefixes: false)); // "1.57 MB"
Roman Numerals
Convert integers (between 1 and 3999) to Roman numerals.
int year = 2024;
Console.WriteLine(year.ToRomanNumeral()); // "MMXXIV"
Financial Formatting
The library provides specialized support for financial domain concepts including Basis Points, Fractional Prices, and Check Writing.
1. Basis Points (BPS)
Convert between raw decimal values and their BPS representation.
using NumberFormatter.Financial;
decimal spread = 0.0125m;
Console.WriteLine(spread.ToBpsString()); // "125 bps"
Console.WriteLine(spread.ToBps()); // 125.0
// Parsing
if (BasisPointFormatter.TryParseBps("50 bps", out decimal result))
{
Console.WriteLine(result); // 0.005
}
2. Fractional Prices (Treasury Markets)
Format and parse prices using market-standard fractions (default denominator: 32).
using NumberFormatter.Financial;
decimal price = 101.5m;
Console.WriteLine(price.ToFractionString(32)); // "101 16/32"
// Parsing
if (FinancialRounding.TryParseFraction("99 2/32", out decimal result))
{
Console.WriteLine(result); // 99.0625
}
3. Spelled-out Numbers (Check Writing)
Convert decimals directly into words for check writing or legal documents.
using NumberFormatter.Financial;
decimal amount = 5432.10m;
Console.WriteLine(amount.ToWords()); // "Five Thousand Four Hundred Thirty-Two and 10/100"
// With currency units
Console.WriteLine(amount.ToCheckWords("Dollars", "Dollar"));
// "Five Thousand Four Hundred Thirty-Two Dollars and 10/100"
Breaking Changes
If you are upgrading from an earlier version, please note the following breaking changes:
- Object Allocation Removal (
ShortNumberFormatOptions): To significantly improve performance and eliminate heap allocations during formatting,ShortNumberFormatOptionshas been changed from aclassto arecord struct. If your code passed this configuration object between methods and modified it expecting reference type semantics, you must update your code to either pass byrefor assign the modified struct back to your variable. - Deprecation of Public Parsing Expositions: The public static dictionaries
SuffixMultipliersandCurrencySymbolspreviously exposed onShortNumberJsonConverter<T>andCurrencyDictionaryConverterhave been removed. This logic is now efficiently managed and centralized within the core library'sNumberFormatter.TryParsemethod, avoiding duplicate Regex and allocation overhead.
ASP.NET Core Integration
1. Register the JSON Converter (Global)
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new ShortNumberJsonConverterFactory());
})
.AddFinancialFormatters(); // Registers BPS and Fraction converters
All numeric properties in API responses will be formatted with default settings. The converter also supports deserialization, allowing values like "1.23M" to be parsed back into numeric form. Nullable types are handled automatically.
2. Per-Property Control with Attribute
public class TradeDto
{
[BasisPoints(decimals: 1)]
public decimal Spread { get; set; }
[FractionPrice(32)]
public decimal BondPrice { get; set; }
public long Quantity { get; set; }
}
Supports recursive property mapping for advanced models:
decimal?(Nullable support)List<decimal>ordecimal[](Collection support)Dictionary<string, decimal>(Dictionary support)
Apply formatting globally per class:
[ShortNumberFormatGlobally(isCurrency: true, decimalPlaces: 2)]
public class FinancialReport
{
public decimal Revenue { get; set; }
public decimal Expenses { get; set; }
public string Title { get; set; }
}
3. Register the DI Service
builder.Services.AddNumberFormatter();
public class MyController : ControllerBase
{
private readonly INumberFormatterService _formatter;
public MyController(INumberFormatterService formatter)
{
_formatter = formatter;
}
public IActionResult Get()
{
var formatted = _formatter.FormatCurrency(1234567.89m, currencyCode: "USD");
return Ok(new { formatted });
}
}
4. Razor Tag Helper
@addTagHelper *, NumberFormatter.AspNetCore
<short-number value="1234567.89" format="currency" currency-code="USD" decimal-places="2" css-class="money"></short-number>
<check-amount value="5432.10" major-currency="Dollars" major-currency-singular="Dollar"></check-amount>
5. View Component
@await Component.InvokeAsync("ShortNumber", new { value = 1234567.89m, isCurrency = true, currencyCode = "EUR" })
6. Currency Dictionary Serialization
options.JsonSerializerOptions.Converters.Add(new CurrencyDictionaryConverter());
public class Report
{
public Dictionary<string, decimal> InternationalRevenue { get; set; }
}
{
"internationalRevenue": {
"USA": "$5.00M",
"EUR": "€4.00M",
"GBP": "£3.50M"
}
}
Supports round-trip deserialization, converting formatted strings like "$5.00M" back into numeric values.
Options Reference
ShortNumberFormatOptions
| Property | Type | Default | Description |
|---|---|---|---|
| DecimalPlaces | int | 2 | Number of decimal places in output |
| ShowPlusSign | bool | false | Prefix positive numbers with + |
| CurrencySymbol | string? | null | Overrides culture's currency symbol |
| CurrencyPosition | CurrencyPosition | Before | Placement of currency symbol |
| NegativePattern | string | "-n" | Format for negatives: -n, (n), n- |
| CustomSuffixes | string[]? | null | Custom suffixes in ascending magnitude |
| AlwaysShowSuffix | bool | false | Always display suffix even below threshold |
| Threshold | decimal | 1000 | Minimum value to apply suffix |
| PromotionThreshold | decimal | 0.95 | Early promotion factor (0–1) |
Understanding Key Options
- PromotionThreshold – Promotes values close to the next suffix. Example:
950_000 → 0.95M - AlwaysShowSuffix – Forces suffix display even below threshold. Example:
500 → 0.5K
CurrencyPosition Enum
public enum CurrencyPosition
{
Before, // "$1.23K"
After, // "1.23K$"
BeforeWithSpace, // "$ 1.23K"
AfterWithSpace // "1.23K $"
}
Suffix Sets
Available via NumberSuffixes:
- Default –
K,M,B,T,Qa,Qi - Financial – Same as default
- Scientific –
k,M,G,T,P,E
Custom suffixes can be provided via ShortNumberFormatOptions.CustomSuffixes.
Advanced Features
Global Formatting Attribute
[ShortNumberFormatGlobally(isCurrency: true, decimalPlaces: 1)]
public class Summary
{
public decimal TotalSales { get; set; }
public decimal AverageOrder { get; set; }
public int CustomerCount { get; set; }
}
Deserialization Support
All JSON converters support parsing formatted strings back into numeric values, enabling full round-trip scenarios.
Nullable Numeric Handling
ShortNumberNullableJsonConverter<T> ensures proper serialization/deserialization of nullable numeric types.
CurrencyDictionaryConverter Round-Trip
Handles both serialization and deserialization using consistent suffix and currency parsing logic.
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on agdgb.NumberFormatter:
| Package | Downloads |
|---|---|
|
agdgb.NumberFormatter.AspNetCore
ASP.NET Core integration for NumberFormatter – includes JSON converters, tag helpers, and DI extensions for short number formatting. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.1.0 | 134 | 4/5/2026 | |
| 1.0.0 | 140 | 4/2/2026 | |
| 1.0.0-preview.1 | 85 | 3/23/2026 |