Version: 1.6.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 suffix `n`, like so: `12n`, `0n`, and the same restriction on zero as integers applies: `0n` 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 suffix `mutez` after a natural literal, like `10000mutez` or `0mutez`;
• units of `tez`, using the suffix `tz` or `tez`, like `3tz` or `3tez`;
• decimal amounts of `tz` or `tez`, like `12.3tz` or `12.4tez`.

Note that large integral values can be expressed using underscores to separate groups of digits, like `1_000mutez` or `0.000_004tez`.

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
const a = 5 + 10;
// nat + int yields int
const b = 5n + 10;
// tez + tez yields tez
const c: tez = 5mutez + 1tez;
// tez + int or tez + nat is invalid:
// const d : tez = 5mutez + 10n;
// two nats yield a nat
const e: nat = 5n + 10n;
// nat + int yields an int: invalid
// const f : nat = 5n + 10;
const g = 1_000_000;

Tip: you can use underscores for readability when defining large numbers:

let sum : tez = 100_000mutez;

Subtraction​

Subtraction looks as follows.

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

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

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

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

Multiplication​

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

const a = 5 * 5;
const b: nat = 5n * 5n;
// You can also multiply `nat` and `tez`
const c: tez = 5n * 5mutez;

Euclidean Division​

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

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

const a: int = 10 / 3;
const b: nat = 10n / 3n;
const c: nat = 10mutez / 3mutez;

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.

const a = 120;
const b = 9;
const rem1 = a % b; // 3
const c = 120n;
const rem2 = c % b; // 3
const d = 9n;
const rem3 = c % d; // 3
const rem4 = 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`

const a = 37;
const b = 5;
const ediv1 : option<[int , nat]> = ediv(a, b); // Some (7, 2)
const c = 37n;
const ediv2: option<[int , nat]> = ediv(c, b); // Some (7, 2)
const d = 5n;
const ediv3: option<[nat , nat]> = ediv(c, d); // Some (7, 2)
const 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:

const a = int(1n);
const b = 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.

const is_a_nat = is_nat(1);

Increment operator​

Increment opeator increments (adds one to) the value of the binder.

In the prefix position (`++p`) the operator increments the value and returns the latest incremented value.

In the postfix position (`p++`) the operator increments the value but returns the old value before the increment.

const testInc = (() => {
let inc = 0;
// Prefix increment operator
assert(++inc == 1);
assert(inc == 1);
// Postfix increment operator
assert(inc++ == 1);
assert(inc == 2);
})();

Decrement operator​

Decrement opeator decrements (subtracts one from) the value of the binder.

In the prefix position (`--p`) the operator decrements the value and returns the latest decremented value.

In the postfix position (`p--`) the operator decrements the value but returns the old value before the decrement.

const testDec = (() => {
let v = 10;
// Prefix decrement operator
assert(--v == 9);
assert(v == 9);
// Postfix decrement operator
assert(v-- == 9);
assert(v == 8);
})();