Version: 0.43.0

# Math, Numbers & Tez

LIGO offers three built-in numerical types: `int`, `nat` and `tez`. Values of type `int` are integers; values of type `nat` are natural numbers (integral numbers greater than or equal to zero); values of type `tez` are units of measure of Tezos tokens.

• Integer literals are the same found in mainstream programming languages, for example, `10`, `-6` and `0`, but there is only one canonical zero: `0` (so, for instance, `-0` and `00` are invalid).
• Natural numbers are written as digits followed by the annotation `as nat`, like so: `12 as nat`, `0 as nat`, and the same restriction on zero as integers applies: `0 as nat` is the only way to specify the natural zero.

• Tezos tokens can be specified using literals of three kinds:

• units of millionth of `tez`, using the annotation `as mutez` after a natural literal, like `10000 as mutez` or `0 as mutez`;
• units of `tez`, using the annotation `as tez`, like `3 as tez`;
• decimal amounts of `tez` are not supported by JsLIGO, instead the amount should be written as `mutez`.

Note that large integral values can be expressed using underscores to separate groups of digits, like `1_000 as mutez`.

Addition in LIGO is accomplished by means of the `+` infix operator. Some type constraints apply, for example you cannot add a value of type `tez` to a value of type `nat`.

In the following example you can find a series of arithmetic operations, including various numerical types. However, some bits remain in comments as they would otherwise not compile, for example, adding a value of type `int` to a value of type `tez` is invalid. Note that adding an integer to a natural number produces an integer.

// int + int yields int
let a: int = 5 + 10;
// nat + int yields int
let b: int = (5 as nat) + 10;
// tez + tez yields tez
let c: tez = (5 as mutez) + (1 as tez);
// tez + int or tez + nat is invalid:
// let d : tez = (5 as mutez) + (10 as nat);
// two nats yield a nat
let e: nat = (5 as nat) + (10 as nat);
// nat + int yields an int: invalid
// let f : nat = (5 as nat) + 10;
let g: int = 1_000_000;

Pro tip: you can use underscores for readability when defining large numbers:

let sum : tez = 100_000 as mutez;

## Subtraction#

Subtraction looks as follows.

⚠️ Even when subtracting two `nats`, the result is an `int`

let a: int = 5 - 10;
// Subtraction of two nats yields an int
let b: int = (5 as nat) - (2 as nat);
// Therefore the following is invalid
// let c : nat = (5 as nat) - (2 as nat);

From protocol `Ithaca` onwards subtracting values of type `tez` yeilds on optional value (due to the michelson instruction `SUB_MUTEZ`)

let d : option<tez> = (5 as mutez) - (1 as mutez); /* Some (4mutez) */
let e : option<tez> = (1 as mutez) - (5 as mutez); /* None */

## Multiplication#

You can multiply values of the same type, such as:

let a: int = 5 * 5;
let b: nat = (5 as nat) * (5 as nat);
// You can also multiply `nat` and `tez`
let c: tez = (5 as nat) * (5 as mutez);

## Euclidean Division#

In LIGO you can divide `int`, `nat`, and `tez`. Here is how:

⚠️ Division of two `tez` values results into a `nat`

let a: int = 10 / 3;
let b: nat = (10 as nat) / (3 as nat);
let c: nat = (10 as mutez) / (3 as mutez);

LIGO also allows you to compute the remainder of the Euclidean division. In LIGO, it is a natural number.

The behaviour of the `%` operator in JsLIGO is different from JavaScript. In JsLIGO, `%` is a modulus operator and in JavaScript it's a remainder operator. In the case of positive numbers everything is the same, but not with negative numbers.

let a: int = 120;
let b: int = 9;
let rem1: nat = a % b; // 3
let c: nat = 120 as nat;
let rem2: nat = c % b; // 3
let d: nat = 9 as nat;
let rem3: nat = c % d; // 3
let rem4: nat = a % d; // 3

For cases when you need both the quotient and the remainder, LIGO provides the `ediv` operation. `ediv x y` returns `Some (quotient, remainder)`, unless `y` is zero, in which case it returns `None`

let a: int = 37;
let b: int = 5;
let ediv1 : option<[int , nat]> = ediv(a, b); // Some (7, 2)
let c: nat = 37 as nat;
let ediv2: option<[int , nat]> = ediv(c, b); // Some (7, 2)
let d: nat = 5 as nat;
let ediv3: option<[nat , nat]> = ediv(c, d); // Some (7, 2)
let ediv4: option<[int , nat]> = ediv(a, d); // Some (7, 2)

## From `int` to `nat` and back#

You can cast an `int` to a `nat` and vice versa. Here is how:

let a: int = int(1 as nat);
let b: nat = abs(1);

## Checking a `nat`#

You can check if a value is a `nat` by using a predefined cast function which accepts an `int` and returns an optional `nat`: if the result is not `None`, then the provided integer was indeed a natural number, and not otherwise.

let is_a_nat: option<nat> = is_nat(1);