Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Types

long

long Sequence = 9007199254740993;

A 64-bit whole number, exact to its full range — ids, sequence numbers, row versions, byte offsets. It holds the same value whether your code runs on the server or in the browser, including past the point a floating-point number would start rounding.

stable3 examples compiled by CItypesnumbersauthoring

Summary#

A 64-bit whole number, exact across its entire range — roughly ±9.2 quintillion. Use it for values that are counted or issued rather than measured: ids, sequence numbers, row versions, byte offsets. Like every other value in Osy#, a long holds the same value wherever the code runs.

Signature#

long Sequence = 9007199254740993;
int  Count    = 42;                  // `int` is 32-bit — plenty for a count

Description#

Reach for long when a number is an identity or a position, not a measurement. An id issued by a sequence, a version stamp, an offset into a file — these are values where being off by one is not a small error, it is the wrong record. int covers ordinary counts and indexes; use long when the range could plausibly exceed about two billion, or when the value comes from a system that issues 64-bit ids.

Division truncates#

Whole-number division discards the remainder rather than rounding — 7 / 2 is 3, and -7 / 2 is -3. The remainder operator takes the sign of the left operand, so -7 % 2 is -1.

7 / 2          // 3    — not 3.5, and not 4
-7 / 2         // -3   — truncated toward zero
-7 % 2         // -1   — the sign follows the dividend

This holds anywhere in an expression, not only when the two operands are written side by side. A whole-number expression stays a whole-number expression however many steps it takes to get there, so a division at the end of a chain truncates exactly as a direct one does.

(3 - 1) / 3    // 0    — the subtraction is still whole-number arithmetic
(9 - 1) / 3    // 2
count * 2 / 3  // truncates; every operand is a whole number

If you want the fractional answer, ask for one: use decimal (see decimal) or double for the operand. One fractional operand makes the whole expression fractional, wherever it appears in the chain.

7m / 2m        // 3.5
(3 - 1) / 3m   // 0.666… — the decimal operand wins the expression

Arithmetic fails at the edges rather than wrapping#

A long has a fixed width, so there are values arithmetic on it cannot produce. Running past the maximum raises, naming the operands and the range — it does not wrap around to the minimum, and it does not quietly grow into a wider type. Negating the minimum value raises for the same reason: its positive counterpart does not exist in 64 bits.

This is a deliberate difference from C#, which wraps by default. A wrapped total is not an obviously broken value like a blank or an error — it is a plausible number of the wrong sign, and nothing downstream can tell it from a right one. The same expression pushed down into the database raises too, so you get one answer wherever it runs.

If a value can legitimately grow past a long, say so in the type: use decimal (see decimal) or double.

The same answer everywhere#

An Osy# expression means one thing. A long is exact wherever the function runs — server-side, or in-process in the browser (see execution side) — including for values above 2^53, where a floating-point number would silently round to a nearby value. Two ids that differ only in their last digit stay two different ids on both sides, and a comparison that is true on one side is true on the other.

This matters more than it sounds. A rounded id is not an obviously broken value like a blank or an error; it is a perfectly plausible id belonging to a different row. You do not need to know, or care, where a piece of code executes in order to trust that the id you are holding is the one you were given.

Examples#

entity Event {
  long ExternalId;
  [MaxLength(100)] string Name;
}
long PageOffset(long pageIndex, long pageSize) {
  return pageIndex * pageSize;
}
decimal AveragePerItem(decimal total, long items) {
  return items == 0 ? 0m : total / items;
}

See also#

  • decimal — exact base-10 arithmetic, for money and anything with a fractional part
  • execution side — where a function runs; a long is exact on either side

Related

decimal

Exact base-10 arithmetic, for money and anything else where a fraction of a cent matters. It behaves identically…

execution side

Where a function runs. Osy# infers it from the body: a function that reads data runs on the server, a function that…