Skip to content

Proposal for flexible numeric types inspired by the ADA type system #15

@ThyMYthOS

Description

@ThyMYthOS

Proposal for a More Flexible Numeric Type System

First, thank you for the work on this draft. The clear and strict type system is a great foundation.

This proposal suggests enhancing the numeric type system to be more flexible and descriptive, allowing for the precise definition of numeric types with arbitrary precision, particularly for scientific, financial, and hardware-interfacing applications.

Current State

The current specification defines a useful set of fixed-size numeric types (int8...int128, float, double) and a decimal type for high precision. It also lists precision and scale as annotation keywords (3.8.2, 3.8.3).

However, this system could be made more expressive. For example, it's not explicitly clear how to define:

  • A floating-point number with a minimum required decimal precision (not just float or double).
  • A binary fixed-point number with a specific delta (absolute error).
  • A decimal fixed-point number (which decimal + precision + scale may cover, but could be more explicit).
  • A modular (wrap-around) integer type, common in many systems.

Inspiration: The ADA Type System

The ADA language provides an excellent model for defining numeric types based on their requirements rather than their implementation. This makes schemas more portable and semantically rich.

We could adopt a similar model by clarifying and extending the use of the precision and scale keywords, and perhaps introducing a new keyword like model to define the numeric representation.

This proposal suggests an approach that:

  • Uses the standard type property ("number" or "string") to define the storage representation of the value in the JSON document.
  • Adds new "qualifier" properties (e.g., representation, radix) at the same level as type to specify the exact semantics.
    The type is set to "number" if the value can be losslessly represented by a standard JSON number (IEEE 754 double). Otherwise, type is set to "string" to hold the high-precision value.

Proposed Properties

  • type: "number" | "string" (Required)
  • representation: "integer" | "floating" | "fixed" | "rational" | "modular" (Required for this proposal)
  • radix: "binary" | "decimal" (Required for integer, fixed, and floating)
  • precision: integer (Optional. The number of significant bits/digits)
    • For integer and fixed: The total number of bits (if radix: "binary") or digits (if radix: "decimal").
    • For floating: The number of bits (if radix: "binary") or digits (if radix: "decimal") in the mantissa.
  • scale: integer (Optional. Required for fixed representation. The number of fractional bits/digits).
  • modulus: string | number (Optional. Required for modular representation. Same type as indicated by type).
  • minimum: string | number (Optional. The inclusive minimum valid value, as a string for arbitrary precision).
  • maximum: string | number (Optional. The inclusive maximum valid value, as a string for arbitrary precision).
  • exclusiveMinimum: string | number (Optional. The exclusive minimum valid value, as a string for arbitrary precision).
  • exclusiveMaximum: string | number (Optional. The exclusive maximum valid value, as a string for arbitrary precision).

Relationship to Current Definitions

This proposal can be seen as a superset of the numeric types currently defined in the JSON Structure Core draft (e.g., uint8, int32, float64).
Those definitions can be expressed using this proposal:

  • uint8:
 "type": "number",
 "representation": "integer",
 "radix": "binary",
 "precision": 8,
 "minimum": "0",
 "exclusiveMaximum": "256"
  • int32:
 "type": "number",
 "representation": "integer",
 "radix": "binary",
 "precision": 32,
 "minimum": "-2147483648",
 "exclusiveMaximum": "2147483648"
  • float64 (IEEE 754 Double):
 "type": "number",
 "representation": "floating",
 "radix": "binary",
 "precision": 53,
 "minimum": "-1.7976931348623157e+308",
 "maximum": "1.7976931348623157e+308"

(Note: precision is 53 for the bits in the mantissa. Inclusive min/max is standard for float definitions).

The key limitation of the current definitions is that they are restricted to power-of-two, binary types. This proposal extends support to:

  • Non-power-of-two binary types: e.g., a 10-bit integer from a sensor.
  • Decimal types: e.g., DECIMAL(19, 4) for finance, which cannot be losslessly represented by float64.
    This proposal provides a single, unified system for defining all of them.

Examples

Here is how this system would define various numeric types.

  1. Binary Integer
  • Concept: A base-2 integer.
  • Schema (for uint10 sensor reading):
 "type": "number",
 "representation": "integer",
 "radix": "binary",
 "precision": 10,
 "minimum": 0,
 "exclusiveMaximum": 1024
  • Schema (for int128):
 "type": "string",
 "representation": "integer",
 "radix": "binary",
 "precision": 128,
 "minimum": "-170141183460469231731687303715884105728",
 "exclusiveMaximum": "170141183460469231731687303715884105728"
  1. Binary Floating Point
  • Concept: A base-2 floating-point number.
  • Schema (for binary64/double):
    • (See "Relationship to Current Definitions" section)
  • Schema (for arbitrary 512-bit float):
 "type": "string",
 "representation": "floating",
 "radix": "binary",
 "precision": 450
  1. Binary Fixed Point
  • Concept: A base-2 fixed-point number (e.g., Q notation).
  • Schema (for Q24.8, 32-bit total):
 "type": "number",
 "representation": "fixed",
 "radix": "binary",
 "precision": 32,
 "scale": 8,
 "minimum": -8388608,
 "exclusiveMaximum": 8388608
  1. Decimal Floating Point
  • Concept: A base-10 floating-point number.
  • Schema (for decimal128, 34-digit mantissa):
 "type": "string",
 "representation": "floating",
 "radix": "decimal",
 "precision": 34
  1. Decimal Fixed Point
  • Concept: Standard for currency (DECIMAL(p, s)).
  • Schema (for DECIMAL(19, 4)):
 "type": "string",
 "representation": "fixed",
 "radix": "decimal",
 "precision": 19,
 "scale": 4,
 "exclusiveMinimum": "-1000000000000000",
 "exclusiveMaximum": "1000000000000000"
  • Schema (for DECIMAL(10, 2)):
 "type": "number",
 "representation": "fixed",
 "radix": "decimal",
 "precision": 10,
 "scale": 2,
 "exclusiveMinimum": -100000000,
 "exclusiveMaximum": 100000000
  1. Rational Numbers
  • Concept: A number as a ratio of two integers.
  • Schema:
 "type": "string",
 "representation": "rational"
  1. Modular Types
  • Concept: An integer that wraps around.
  • Schema (for mod 360), e.g. heading in degrees:
 "type": "number",
 "representation": "modular",
 "modulus": "360"
  • Schema (for mod 2**256):
 "type": "string",
 "representation": "modular",
 "modulus": "115792089237316195423570985008687907853269984665640564039457584007913129639936",
 "minimum": "0",
 "exclusiveMaximum": "115792089237316195423570985008687907853269984665640564039457584007913129639936"

Benefits of This Approach

  • Backwards-Compatible: Parsers that don't understand the new properties still see a valid JSON type ("number" or "string").
  • Explicit Storage: Clearly separates the logical numeric type from its physical storage in the JSON document.
  • Unambiguous Deserialization: A consumer knows whether to parse a value from a string or use the native number, and knows what precise data type (e.g., Decimal, BigInt) to deserialize it into.
  • Extensible: Unifies all numeric types (current and future) under one flexible system.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions