Question
How can I display a C# decimal value with exactly two decimal places? Calling .ToString() currently shows many decimal digits, but I am using the value to represent dollars and cents and want output such as 12.50. Is there a suitable variation of .ToString() for this?
Short Answer
You will learn how C# numeric format strings control a decimal value's displayed precision. In particular, you will use "F2" and "0.00" to show two digits after the decimal point, and "C" or "C2" when the value should be displayed as currency.
Concept
decimal.ToString() converts a number into text. With no format string, C# chooses a representation that preserves the number's meaningful digits, which can result in more decimal places than a user-facing screen needs.
A numeric format string tells ToString() how the text should look:
"F2"means fixed-point notation with two digits after the decimal separator."0.00"is a custom format that also requires exactly two digits after the separator."C2"means currency formatting with two decimal digits, including a culture-specific currency symbol and separators.
decimal price = 12.5m;
Console.WriteLine(price.ToString("F2")); // 12.50
Console.WriteLine(price.ToString("0.00")); // 12.50
Formatting changes the text you display; it does not change the original decimal variable. This distinction matters: calculate with numeric values, then format only at the boundary where you show a value to a person, write a report, or export text.
Mental Model
Think of a decimal as the amount written in an accounting ledger, and ToString("F2") as the print layout for that ledger.
The stored value can contain more precision, but the printed layout reserves exactly two spaces after the decimal separator:
8becomes8.008.4becomes8.408.456is printed as8.46
The layout affects what readers see, not the underlying ledger entry.
Syntax and Examples
Use ToString with a standard or custom numeric format string.
decimal amount = 49.987m;
string fixedAmount = amount.ToString("F2");
string customAmount = amount.ToString("0.00");
Console.WriteLine(fixedAmount); // 49.99
Console.WriteLine(customAmount); // 49.99
Both examples display two decimal places. They also round when the value has more than two decimal places.
For a monetary value shown to a user, currency formatting is often clearer:
using System.Globalization;
decimal amount = 1234.5m;
Console.WriteLine(amount.ToString("C2", CultureInfo.GetCultureInfo("en-US")));
// $1,234.50
Console.WriteLine(amount.ToString("C2", CultureInfo.GetCultureInfo("en-GB")));
// £1,234.50
"C2" uses the supplied culture to choose the currency symbol, decimal separator, and thousands separator. Use a specific culture when output must be consistent regardless of the computer's regional settings.
Step by Step Execution
Consider this code:
decimal subtotal = 19.995m;
string displayedSubtotal = subtotal.ToString("F2");
Console.WriteLine(displayedSubtotal);
subtotalstores the numericdecimalvalue19.995.ToString("F2")asks C# to produce fixed-point text with two fractional digits.- Since three fractional digits exist, the result is rounded for display.
displayedSubtotalcontains the string"20.00".Console.WriteLineprints20.00.
The original variable is still numeric:
Console.WriteLine(subtotal); // 19.995
If business rules require you to round the value before later calculations, round the decimal explicitly instead of relying only on display formatting:
decimal roundedSubtotal = decimal.Round(subtotal, 2, MidpointRounding.AwayFromZero);
Real World Use Cases
- Checkout pages: Display an item price as
15.00rather than15. - Invoices and receipts: Use
"C2"to show amounts with a currency symbol and grouping separators. - Financial reports: Use
"N2"for a two-decimal number with thousands separators but no currency symbol, such as1,234.50. - CSV or text exports: Use
"F2"together with an invariant culture when another system requires a period as the decimal separator. - API logs and diagnostics: Limit displayed precision so logs remain readable, while retaining the original numeric value for calculations.
Real Codebase Usage
In production code, formatting usually happens near the presentation layer rather than inside calculation logic.
public string FormatPrice(decimal price, CultureInfo culture)
{
return price.ToString("C2", culture);
}
For an application whose culture is chosen per request or per user, pass that culture into the formatter. This prevents accidentally displaying a US-style amount to a user who expects another locale.
For machine-readable output, use an explicit culture rather than the current machine culture:
using System.Globalization;
decimal amount = 42.5m;
string valueForExport = amount.ToString("F2", CultureInfo.InvariantCulture);
Console.WriteLine(valueForExport); // 42.50
A common validation pattern is to keep values as decimal until they are displayed or serialized:
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount));
}
return amount.ToString("C2", culture);
This avoids parsing formatted strings back into numbers later.
Common Mistakes
Using double for currency
Binary floating-point types such as double cannot represent many decimal fractions exactly. Prefer decimal for dollar-and-cent calculations.
// Avoid for money calculations.
double price = 0.1 + 0.2;
// Prefer.
decimal price = 0.1m + 0.2m;
The m suffix makes a numeric literal a decimal.
Assuming formatting changes the numeric value
decimal amount = 12.345m;
string text = amount.ToString("F2"); // "12.35"
Console.WriteLine(amount); // Still 12.345
Use decimal.Round if the stored or subsequently calculated value itself must be rounded.
Using "0.##" when exactly two places are required
decimal amount = 12.5m;
Console.WriteLine(amount.ToString("0.##")); // 12.5
# means an optional digit. Use "0.00" or "F2" when trailing zeros must appear.
Hard-coding a currency symbol
string text = "$" + amount.ToString("F2");
This can be wrong for users in another region and misses culture-specific formatting. Prefer amount.ToString("C2", culture).
Relying on the current culture for data interchange
A value formatted on one computer may use 12,50; another may use 12.50. For fixed machine formats, use CultureInfo.InvariantCulture.
Comparisons
| Format | Example for 1234.5m in en-US | Best use |
|---|---|---|
ToString() | 1234.5 | General conversion when a fixed display precision is not needed |
ToString("F2") | 1234.50 | Exactly two decimal places, without grouping or a currency symbol |
ToString("0.00") | 1234.50 | Exactly two decimal places using a custom format |
ToString("N2") | 1,234.50 | Readable numbers with thousands separators |
ToString("C2") | $1,234.50 | Currency shown to users |
decimal.Round(amount, 2) | numeric 1234.50 | Changing the numeric value used in later calculations |
"F2" and "0.00" produce similar results for ordinary positive amounts. "F2" is a standard fixed-point format; "0.00" gives you more control if you later need a custom layout, such as "$0.00" for a fixed literal symbol.
Cheat Sheet
using System.Globalization;
decimal amount = 12.5m;
amount.ToString("F2"); // "12.50"
amount.ToString("0.00"); // "12.50"
amount.ToString("N2", CultureInfo.GetCultureInfo("en-US")); // "12.50" or grouped for larger values
amount.ToString("C2", CultureInfo.GetCultureInfo("en-US")); // "$12.50"
amount.ToString("F2", CultureInfo.InvariantCulture); // "12.50"
- Use
decimaland themsuffix for monetary values. 0requires a digit;#makes a digit optional."F2"and"0.00"display exactly two fractional digits.- Formatting returns a
string; it does not modify the number. - Use
decimal.Roundwhen later calculations must use the rounded value. - Use an explicit
CultureInfofor consistent output or user-specific currency formatting.
FAQ
How do I show exactly two decimal places in C#?
Use amount.ToString("F2") or amount.ToString("0.00").
What is the difference between F2 and 0.00?
Both normally show two decimal places. F2 is a standard fixed-point format, while 0.00 is a custom format that can be extended with your own literals and digit rules.
Does ToString("F2") round a decimal value?
It rounds the textual result to two decimal places. The original decimal value is unchanged.
How do I round the actual decimal value to two places?
Use decimal.Round(amount, 2). Choose a MidpointRounding option explicitly if your business rules require a specific midpoint behavior.
Should I use decimal or double for dollars and cents?
Use decimal for monetary calculations. It is designed for precise base-10 decimal arithmetic.
How do I include a currency symbol?
Use amount.ToString("C2", culture), supplying a suitable CultureInfo, such as CultureInfo.GetCultureInfo("en-US").
Why does my decimal separator appear as a comma?
Numeric formatting follows the active culture. Pass CultureInfo.InvariantCulture for a fixed period decimal separator in machine-readable output.
Mini Project
Description
Build a small receipt formatter for a checkout workflow. It calculates a subtotal and tax as decimal values, then formats the final output as user-friendly currency without converting values to strings during calculation.
Goal
Create a console receipt that displays prices, tax, subtotal, and total using two decimal places.
Requirements
- Store all monetary amounts as
decimalvalues. - Calculate the subtotal from at least two item prices.
- Calculate tax from the subtotal using a decimal tax rate.
- Display each monetary value with a currency symbol and two decimal places.
- Use an explicit
en-USculture for consistent output.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.