Introduction and Motivation
From the LogicBlox 3.x series to 4.0, we’re going to encourage migrating applications from using floating-point binary numbers to fixed-precision decimal numbers. We propose introducing a new unambiguous syntax for decimal and float literals on 3.10 and 4.0; moreover, we will parse literals of the form ‘2.71’ as decimals on 4.0, rather than as floats as on 3.x.
3.10 and 4.0
Semantics and Examples
Currently in 3.10, float literals have the form ‘2.71’, but there is no literal syntax for decimals. Our proposal consists of two parts:
1. Adding unambiguous syntax for floats and decimals literals on 3.10 and 4.0:
We’re going to add two new syntactic forms with a suffix ‘d’ or ‘f’ to distinguish the type: ‘2.71d’ for decimal and ‘2.71f’ for float.
2. Reinterpreting numeric literals without postfix as decimal literals to encourage the use of decimals. For the existing literal syntax:
On 3.10, we’ll continue to parse ‘2.71’ as a float.
On 4.0, we’ll parse ‘2.71’ as a decimal instead of a float. We don’t plan on supporting the exponent notation ‘2.71E8’ for decimals.
Decimal numbers have better behavior which leads to improved accuracy, efficiency, and safety over floats. Specifically,
- Decimal addition is associative and thus enables total aggregations to be done much more efficiently and accurately. For comparison, floating-point addition is not associative, which makes aggregations require expensive data structures and still yields inexact answers.
- Decimal arithmetic checks for overflow and aborts a transaction, as opposed to silent floating-point overflows that can be hard to detect.
More details can be found in Todd Veldhuizen’s proposal for fixed-point decimal types.
This syntax change will break any existing code that uses float literals with predicates that are explicitly typed as floats. For instance, ‘float:add[2.71, 3.14]’ will be flagged as a compile-time type error. Similarly, ‘float_type_predicate(2.71)’ will similarly be a compile-time error, assuming ‘float_type_predicate’ has the type ‘float’.
There are two straightforward paths for migration. Our recommended migration path is to change the *code*: an existing built-in operation such as ‘float:add[2.71, 3.14]’ should be replaced by the polymorphic built-in operation ‘2.71 + 3.14’, or ‘add[2.71, 3.14]’; a user-defined predicate ‘float_type_predicate(x) -> float(x)’ that takes a float should instead take a decimal ‘float_type_predicate(x) -> decimal(x)’. Alternatively, if you prefer to keep on using floats, you can use the new unambiguous syntax ‘2.71f’ for float literals.