Decimal
Decimal is exact base-ten arithmetic such as money; a number literal adapts to it and keeps every digit and its scale, and both back ends compute it.
Decimal is the type for money and anything else where base-ten rounding has to be exact - 0.1 + 0.2 has to be
0.3, which no binary floating-point type can promise. The type is declared in std/number, and a decimal literal
adapts to it the same way an integer literal adapts to Int8. Both back ends compute it, and a literal keeps every
digit it is written with.
Example#
const price: Decimal = 19.99
const quantity: Int = 3
print(price * Decimal.from(quantity))Syntax#
Decimal the type
const price: Decimal = 19.99 a literal, adapted like any other numeric literal
Decimal.tryFrom("19.99") a value read from text, a ResultRules#
Decimalis declarednative type Decimal with Signed, Hash, next to the other numeric types instd/number. It has the same trait list a signed integer type has, so the same arithmetic and comparison operators are written the same way once it runs.A number literal adapts to
Decimalthe way any numeric literal adapts to its expected type, and keeps every digit it is written with.19.99is the number 1999 at the scale 2,1.50keeps its trailing zero,0xFFis 255 at the scale 0,1e3has the scale -3 and-19.99is the negation of19.99. There is no limit on the digits; only a written scale outside ofInt32(1e-3000000000) is a compile error. A literal never passes through aFloat64, and without an expected type19.99stays aFloat64.Decimal.zeroandDecimal.oneare the literals0and1. In amatch, a literal pattern compares by numeric value like==, so1.0matches1.00, and amatchon aDecimalalways needs a wildcard arm.DecimalisHash, unlikeFloat32andFloat64. Exact base-ten arithmetic has nonanand no-0.0to complicate equality, so aDecimalcan be aMapkey.+,-and*are exact, and/stops at 34 significant digits. A quotient with an exact answer keeps it; any other is rounded half to even.roundedanddividedtake a scale and one of the six cases ofRounding, and%takes the sign of the dividend. Dividing by zero panics.A
Decimalkeeps every digit through JSON, YAML and TOML. JSON and YAML write the number with the digits ofshow()(19.90stays19.90) and read a number into aDecimalfrom its text, so0.1234567890123456789, a value of 40 digits and1e3survive; a string is refused. TOML has no decimal type: aDecimalis written as a string and read back from one. AFloat64field still reads a number as the nearestFloat64.
What this is not#
Decimal is not Float64 with more digits. Float64 is binary floating point and is not Hash; Decimal is
base-ten and is Hash, because it does not have the two IEEE-754 exceptions that make hashing a float unsound. See
Floating-point numbers for what those exceptions are.
A Decimal literal is not a Float64 rounded afterwards. const price: Decimal = 19.99 is exactly 1999 at the
scale 2, the same value Decimal.tryFrom("19.99") reads from text, and a literal with more digits than a Float64
holds keeps all of them.
Related#
- Floating-point numbers - why
Float32/Float64are notHash, andDecimalis. - Integers - the sized integer types
Decimalsits next to instd/number. - Built-in types -
Decimalin the context of every other numeric type.