Fixed-Point Numbers and Functions
Fixed-point numbers
Currently only the 64-bit wide Fix64
and UFix64
types are available. More fixed-point number types will be added in a future release.
Fixed-point numbers are useful for representing fractional values. They have a fixed number of digits after a decimal point.
They are essentially integers which are scaled by a factor. For example, the value 1.23 can be represented as 1230 with a scaling factor of 1/1000. The scaling factor is the same for all values of the same type and stays the same during calculations.
Fixed-point numbers in Cadence have a scaling factor with a power of 10, instead of a power of 2 (i.e., they are decimal, not binary).
Signed fixed-point number types have the prefix Fix
, have the following factors, and can represent values in the following ranges:
Fix64
: Factor 1/100,000,000; -92233720368.54775808 through 92233720368.54775807
Unsigned fixed-point number types have the prefix UFix
, have the following factors, and can represent values in the following ranges:
UFix64
: Factor 1/100,000,000; 0.0 through 184467440737.09551615
Fixed-point number functions
Fixed-Point numbers have multiple built-in functions you can use:
-
_10view fun toString(): String
Returns the string representation of the fixed-point number.
_10let fix = 1.23_10_10fix.toString() // is "1.23000000" -
_10view fun toBigEndianBytes(): [UInt8]
Returns the byte array representation (
[UInt8]
) in big-endian order of the fixed-point number._10let fix = 1.23_10_10fix.toBigEndianBytes() // is `[0, 0, 0, 0, 7, 84, 212, 192]`
All fixed-point types support the following functions:
-
_10view fun T.fromString(_ input: String): T?
Attempts to parse a fixed-point value from a base-10 encoded string, returning
nil
if the string is invalid.For a given fixed-point numeral
n
of typeT
,T.fromString(n.toString())
is equivalent to wrappingn
up in anoptional
.Strings are invalid if:
- they contain non-digit characters.
- they don't fit in the target type.
- they're missing a decimal or fractional component. For example, both
0.
and.1
are invalid strings, but0.1
is accepted.
For signed types like
Fix64
, the string may optionally begin with a+
or-
sign prefix.For unsigned types like
UFix64
, sign prefices are not allowed.Examples:
_11let nil1: UFix64? = UFix64.fromString("0.") // nil, fractional part is required_11_11let nil2: UFix64? = UFix64.fromString(".1") // nil, decimal part is required_11_11let smol: UFix64? = UFix64.fromString("0.1") // ok_11_11let smolString: String = "-0.1"_11_11let nil3: UFix64? = UFix64.fromString(smolString) // nil, unsigned types don't allow a sign prefix_11_11let smolFix64: Fix64? = Fix64.fromString(smolString) // ok -
_10view fun T.fromBigEndianBytes(_ bytes: [UInt8]): T?
Attempts to parse an integer value from a byte array representation (
[UInt8]
) in big-endian order, returningnil
if the input bytes are invalid.For a given integer
n
of typeT
,T.fromBigEndianBytes(n.toBigEndianBytes())
is equivalent to wrappingn
up in an optional.The bytes are invalid if:
- the length of the bytes array exceeds the number of bytes needed for the target type.
- they don't fit in the target type.
Examples:
_10let fortyTwo: UFix64? = UFix64.fromBigEndianBytes([0, 0, 0, 0, 250, 86, 234, 0]) // ok, 42.0_10_10let nilWord: UFix64? = UFix64.fromBigEndianBytes("[100, 22, 0, 0, 0, 0, 0, 0, 0]") // nil, out of bounds_10_10let nilWord2: Fix64? = Fix64.fromBigEndianBytes("[0, 22, 0, 0, 0, 0, 0, 0, 0]") // // nil, size (9) exceeds number of bytes needed for Fix64 (8)_10_10let negativeNumber: Fix64? = Fix64.fromBigEndianBytes([255, 255, 255, 255, 250, 10, 31, 0]) // ok, -1