mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
115 lines
4.3 KiB
Markdown
115 lines
4.3 KiB
Markdown
# Allow ties in floating literals
|
|
|
|
<!--
|
|
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
Exceptions. See /LICENSE for license information.
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
-->
|
|
|
|
[Pull request](https://github.com/carbon-language/carbon-lang/pull/866)
|
|
|
|
<!-- toc -->
|
|
|
|
## Table of contents
|
|
|
|
- [Problem](#problem)
|
|
- [Background](#background)
|
|
- [Proposal](#proposal)
|
|
- [Details](#details)
|
|
- [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)
|
|
- [Alternatives considered](#alternatives-considered)
|
|
|
|
<!-- tocstop -->
|
|
|
|
## Problem
|
|
|
|
Proposal [#143](https://github.com/carbon-language/carbon-lang/pull/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](p0143.md#ties) 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
|
|
10<sup>B</sup>, 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 10<sup>9</sup> 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](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even).
|
|
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
|
|
|
|
- [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)
|
|
- This improves the ease of both reading and writing floating-point
|
|
literals that would result in ties.
|
|
- This improves the language consistency, by performing the same rounding
|
|
when converting literals as is performed by default when converting
|
|
runtime values.
|
|
- [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)
|
|
- It is unlikely that making an arbitrary but consistent rounding choice
|
|
will harm safety or program correctness.
|
|
- [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)
|
|
- [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments)
|
|
- [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)
|
|
- This rule, likely because it is the IEEE default rounding mode, already
|
|
appears to be used by major C++ compilers such as Clang, GCC, MSVC, and
|
|
ICC.
|
|
|
|
## 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.
|