Integers and numbers
Overview
Motoko offers a variety types to represent integers and natural numbers, with the usual suite of arithmetic operators (+
, -
, *
, '/' etc.) and comparison operators (==
, !=
, <
, >
, <=
, >=
).
The types Int
and Nat
are unbounded, meaning their values can grow to arbitrary size, limited only by memory.
The type Nat
is a subtype of Int
, so you can always supply a value of type Nat
where and Int
is expected but not vice versa.
Motoko also provides bounded, or fixed-size integers and naturals, using a suffix to indicate the size of the type, in bits.
Thus Int8
, Int16
and Int32
and Int64
are 8-, 16-, 32- and 64-bit integer types, while Nat8
, Nat16
, Nat32
, and Nat64
are 8-, 16-, 32- and 64-bit natural types.
An arithmetic operation on a value of a fixed-size type will trap if its result exceeds the bounds of the fixed-size type, either due to overflow or underflow.
For example, 255 : Nat8 + 3
traps, because 258 is too large for a Nat8
.
Wrapping, non-trapping, versions of the usual arithmetic operations, performing modular arithmetic, are available by suffixing the usual operator with a %
. For example, 255 : Nat8 +% 3
evaluates to 2
.
The type of an integer or natural constant is determined by the textual context
of the constant, defaulting to Int
for negative constants and Nat
for positive ones.
Otherwise, the type of a constant can be indicated using a type annotation, for example 0 : Nat8
.
One can force a nonnegative constant to be interpreted as an Int
using an explicit sign, for example +1
is the Int
one.
For convenience, in-place updates of a variable or array element can be written by using a compound assignment operator, combining an arithmetic operation with the assignment operator :=
. E.g. x += 1
is short-hand for x := x + 1
and combines addition +
with assignment.
Motoko does not provide any implicit conversions between numeric types. Instead, base library functions like Nat8.toNat
and Nat8.fromNat
should be used for explicit conversion.
To illustrate working with numbers, here is an example calculator program that creates a single actor with several public entry-point functions to perform basic arithmetic operations using integers.
Using integers
// This single-cell calculator defines one calculator instruction per
// public entry point (add, sub, mul, div).
// Create a simple Calc actor.
actor Calc {
var cell : Int = 0;
// Define functions to add, subtract, multiply, and divide
public func add(n:Int) : async Int { cell += n; cell };
public func sub(n:Int) : async Int { cell -= n; cell };
public func mul(n:Int) : async Int { cell *= n; cell };
public func div(n:Int) : async ?Int {
if ( n == 0 ) {
return null // null indicates div-by-zero error
} else {
cell /= n; ?cell
}
};
// Clear the calculator and reset to zero
public func clearall() : async Int {
if (cell : Int != 0)
cell -= cell;
return cell
};
};
You might notice that this sample code uses integer (Int
) data types, enabling you to use positive or negative numbers. If you wanted to restrict the functions in this calculator code to only use positive numbers, you could change the data type to only allow natural (Nat
) data.
This program supports the following function calls:
The
add
function call accepts input and performs addition.The
sub
function call accepts input and performs subtraction.The
mul
function call accepts input and performs multiplication.The
div
function call accepts input and performs division. It also includes code to prevent the program from attempting to divide by zero.The
clearall
function clears thecell
value stored as the result of previous operations, resetting thecell
value to zero.