Resources Numerical accuracy Calculation policy

Numbers sent between people editing together

How a number in an edit is written into a Studio Live message and read back on the other side.

How the precision is kept

Edits travel as MessagePack, written and read by this file's own code. A whole number inside the safe integer range is written as an integer; every other number is written as an 8-byte 64-bit float. The writer never produces the 4-byte 32-bit float form, so a coordinate arrives with the same 64 bits it left with.

Calculations under this policy

5 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.

live-client.js Shared shell, every app 64-bit 5 calculations Reviewed

Tests tools/live-test/test-client.mjs

Integer or float

64-bit

Decides how a number is written.

A value that is an integer and a safe integer goes to the integer writer; anything else, including fractions, NaN, the infinities and integers beyond 2^53, goes to the 64-bit float writer.

  • live-client.js
  • line 80
case 'number': return Number.isInteger(v) && Number.isSafeInteger(v) ? this.int(v) : this.float(v);

Writing a float

64-bit

Writes a number as 8 bytes.

Type byte 0xcb and DataView.setFloat64: all 64 bits are sent. There is no 32-bit float writer in the file.

  • live-client.js
  • line 135
float(v) { this.u8(0xcb); this.need(8); this.view.setFloat64(this.p, v); this.p += 8; }

Writing an integer

Exact

Writes a whole number in the shortest integer form that holds it.

The forms are chosen by range, from one byte up to 64 bits, and each holds the integer exactly. Zero and negative zero both take the first branch and are written as the byte 0.

  • live-client.js
  • lines 111 to 124
int(v) {
  if (v >= 0) {
    if (v < 128) return this.u8(v);
    if (v < 0x100) { this.u8(0xcc); return this.u8(v); }
    if (v < 0x10000) { this.u8(0xcd); return this.u16(v); }
    if (v < 0x100000000) { this.u8(0xce); return this.u32(v); }
    return this.big(BigInt(v));
  }
  if (v >= -32) return this.u8(v & 0xff);
  if (v >= -128) { this.u8(0xd0); this.need(1); this.view.setInt8(this.p, v); this.p += 1; return; }
  if (v >= -32768) { this.u8(0xd1); this.need(2); this.view.setInt16(this.p, v); this.p += 2; return; }
  if (v >= -2147483648) { this.u8(0xd2); this.need(4); this.view.setInt32(this.p, v); this.p += 4; return; }
  return this.big(BigInt(v));
}

Reading a float

64-bit

Reads a 4-byte or an 8-byte float from a message.

Type 0xcb is read with getFloat64. Type 0xca is read with getFloat32 and widened; this file's writer never sends it, so a value read that way came from another encoder and carries 32-bit precision.

  • live-client.js
  • lines 196 to 197
case 0xca: { this.need(4); const x = v.getFloat32(this.p); this.p += 4; return x; }
case 0xcb: { this.need(8); const x = v.getFloat64(this.p); this.p += 8; return x; }

Reading a 64-bit integer

Exact

Reads an unsigned or signed 64-bit integer.

The value is read as a BigInt and turned into a number only when it is within ±9007199254740991, where a 64-bit float holds it exactly; otherwise it stays a BigInt.

  • live-client.js
  • lines 201 to 205
case 0xcf: { this.need(8); const x = v.getBigUint64(this.p); this.p += 8; return x <= 9007199254740991n ? Number(x) : x; }
case 0xd0: { this.need(1); const x = v.getInt8(this.p); this.p += 1; return x; }
case 0xd1: { this.need(2); const x = v.getInt16(this.p); this.p += 2; return x; }
case 0xd2: { this.need(4); const x = v.getInt32(this.p); this.p += 4; return x; }
case 0xd3: { this.need(8); const x = v.getBigInt64(this.p); this.p += 8; return x >= -9007199254740991n && x <= 9007199254740991n ? Number(x) : x; }

In detail

Method
MessagePack: integer forms for safe integers, type 0xcb (float 64) for every other number, 64-bit integer forms for BigInt.
Number types
64-bit floats and integers; BigInt for 64-bit integers beyond ±(2^53 − 1).
Limits
Negative zero counts as an integer and is written as 0, so its sign is not kept. The reader accepts a 32-bit float (type 0xca) if another program sends one.

Approach: 64-bit, direct

Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.

Every policy that takes this approach