Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Function

format specifiers

$"{value:F2}" · value.ToString("F2") · Convert.ToString(value, "F2")

Formats a number to a string with a .NET format specifier — F2 for two decimal places, N0 for a grouped whole number, C for currency, P for a percentage. Formatting is invariant, so the same value renders identically in the browser and on the server.

stable2 examples compiled by CIfunctiontextformattingstdlib

Summary#

A number becomes a string with a format specifier: $"{total:F2}" renders 1.5 as "1.50". The same specifier works through total.ToString("F2") and Convert.ToString(total, "F2") — they are three spellings of one operation.

Signature#

$"{<value>:<format>}"
<value>.ToString(<format>)
Convert.ToString(<value>, <format>)

Description#

The specifiers#

A specifier is a letter plus an optional precision, e.g. F2, N0, P1. Precision defaults to 2 where it applies.

Specifier1234.5678 renders asWhat it is
F21234.57fixed-point — the everyday one, and what money wants
N21,234.57number — same as F, plus group separators
C¤1,234.57currency
P2123,456.78 %percent — multiplies by 100
E1.234568E+003scientific
G1234.5678general — the plain digits
D5(integers only) 00042decimal digits, zero-padded
X(integers only) 2Ahexadecimal

Three of these behave in ways worth knowing before you rely on them:

  • Currency uses ¤, the generic currency sign — not $. Formatting is invariant (see below), and the invariant culture has no country, so it has no currency symbol either. If you want $ or , write it: $"${total:N2}".
  • A negative currency is wrapped in parentheses: -1.5 renders as (¤1.50), not -¤1.50.
  • D and X are integer-only. Applied to a decimal they raise an error, even for a whole number like 0.

Rounding#

Formatting rounds away from zero: 1.005 to two places is 1.01, and -1.005 is -1.01. Because a decimal holds exact base-10 digits, that is the digit you actually wrote — not the nearest binary approximation of it. A value that rounds to zero prints as 0, never -0.

It renders the same everywhere#

Formatting is invariant: it does not consult the machine's locale. A price is the same string in the browser, on the server, in a log line, and in a test — and it does not change when a user in another country opens the page.

That is also why formatting runs in the browser, with no round trip: rendering a grid of prices is local work.

Custom patterns#

A custom pattern like "#,##0.00" or "0.00" also works, and does exactly what it does in C#. Note that a custom pattern is formatted on the server, so a UI action using one costs a network round trip where a standard specifier would not — prefer N2 over #,##0.00 when they give the same answer.

Examples#

string PriceLabel(decimal amount) {
  return $"{amount:N2}";
}
// PriceLabel(1234.5m)  ->  "1,234.50"
string Summary(decimal rate, int reference) {
  return $"{rate:P1} · ref {reference:D6}";
}
// Summary(0.0825m, 42)  ->  "8.3 % · ref 000042"

See also#

Related

String interpolation & format specifiers

Build a string from literal text and embedded expressions with $"…{expr}…". A hole may carry a .NET format specifier…

execution side

Where a function runs. Osy# infers it from the body: a function that reads data runs on the server, a function that…

decimal

Exact base-10 arithmetic, for money and anything else where a fraction of a cent matters. It behaves identically…