Summary#
The platform numeric types are int (Int32), long (Int64), decimal, and double. Numeric literals
follow C#, with no divergence at all: a bare integer is int, a bare decimal-point literal (2.5) is a
double, L makes a long, m a decimal, d a double. There is no float type; 2.5f is a
pointed compile error.
⚠ This page said the opposite until 2026-08-31, describing a bare 2.5 as a decimal "money-safe
default". That divergence was real and was removed on 2026-08-12; the page was not updated with it, so
it taught a spelling the compiler rejects — decimal Price() { return 19.99; } does not compile.
Signature#
5 // int
5000000000L // long (values past int.MaxValue need the suffix)
2.5 // double — same as C#, and same as every other unsuffixed fractional literal
2.5m // decimal — what money is written as
2.5d // doubleDescription#
- No
float. The platform numeric model has no float type;2.5frefuses withfloat literals … are not supported — the platform numeric types are int/long/decimal/double. - Bare
2.5is adouble, exactly as in C#. It was a decimal until 2026-08-12, and that was the one place Osy#'s literals disagreed with the language they mirror — a disagreement invisible until arithmetic overflows. A canvas whose fields were alldoubleran entirely in decimal because every literal initialising them was one, and threw "value was either too large or too small for a Decimal" naming a type the source never wrote. - Money is safe BECAUSE of this, not despite it. C#'s rule is a PAIR:
1.0is a double AND there is no implicitdouble→decimal. Osy# keeps both halves, sodecimal price = 19.99;is a compile error and the author writes19.99m— strictly safer than a default that made every literal a decimal whether the surrounding expression wanted one or not. - Arithmetic runs in the decimal lattice (matching Postgres): a
doubleoperand behaves like any non-integral number —5d / 2 == 2.5(a double defeats integer truncation, as in C#), while int÷int truncates (5 / 2 == 2, SQL parity). - Round-trip: suffixed literals persist as typed literal nodes and decompile ALWAYS suffixed
(
5000000000L,5d), so the canonical form re-lexes identically. - Durable: across a suspend/resume, a
doublelocal resumes asdecimal(the codec's numeric normalization — the same value under the decimal arithmetic lattice). constcomposes:const double factor = 1.5d;folds and inlines like every const.
Examples#
long Big() { return 5000000000L; } // past int.MaxValue — needs the L
double Half() { return 5d / 2; } // == 2.5 — the double defeats integer truncation
decimal Price() { return 19.99m; } // money takes the m — a bare 19.99 is a double and will not convert
double Rate() { const double f = 1.5d; return f; }See also#
- Typed locals — declared types + the constant conversion (
double h = 2.5;works) - const — const folding and inlining