Allow ties in floating literals

Pull request

Table of contents

Problem

Proposal #143 suggested that we do not allow ties in floating-point literals. That is, given a literal whose value lies exactly half way between two representable values, we should reject rather than arbitrarily picking one of the two possibilities.

However, the statistical argument presented in that proposal misses an important fact: the distribution of the values that are exactly half way between representable values includes several values of the form A x 10B, where A and B are small integers.

For example, the current rule rejects this very reasonable looking code:

var v: f32 = 9.0e9;

… because 9 x 109 lies exactly half way between the nearest two representable values of type f32, namely 8999999488 and 9000000512. Similar examples exist for larger floating point types:

// Error, half way between two exactly representable values.
var w: f64 = 5.0e22;

We would also reject an attempted workaround such as:

var v: f32 = 5 * 1.0e22;

… because the literal arithmetic would be performed exactly, resulting in the same tie. A workaround such as

var v1: f32 = 5.0e22 + 1.0;
var v2: f32 = 5.0e22 - 1.0;

… to request rounding upwards and downwards, respectively, would work. However, these seem cumbersome and burden the Carbon developer with floating-point minutiae about which they very likely do not care.

Background

For background on the ties-to-even rounding rule, see this Wikipedia article. The ties-to-even rule is the default rounding mode specified by ISO 60559 / IEEE 754.

Proposal

Instead of rejecting exact ties, we use the default IEEE floating point rounding mode: we round to even.

Details

See design changes.

Rationale based on Carbon’s goals

Alternatives considered

We could round to even only for decimal floating-point literals, and still use the rule that ties are rejected for hexadecimal floating point. In the latter case, a tie means that too many digits were specified, and the trailing digits were exactly 80000....

However, because we support arithmetic on literals, forming other literals, this would mean that whether a literal was originally written in hexadecimal would form part of its value and thereby part of its type. There would also be problems with literals produced by arithmetic. The complexity involved here far outweighs any perceived benefit of diagnosing mistyped literals.