Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: floating point literals #71

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions eeps/eep-0075.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
Author: Richard Carlsson <carlsson.richard(at)gmail(dot)com>
Status: Draft
Type: Standards Track
Created: 7-Jan-2025
Erlang-Version: OTP-28.0
Post-History:
****
EEP 75: Based Floating Point Literals
----

Abstract
========

This EEP adds floating point literals using other bases than ten, such
as 16 or 2, for exact text representation, as also found in Ada and
C99/C++17.

Rationale
=========

Computers represent floating point numbers in binary, but such numbers
are typically printed using base ten, for example `0.314159265e1`. In
order to preserve the exact bit level precision when writing a printed
number as text and later reading it back again, it is better to use a
base that matches the internally used base, such as 16 for a compact
but still exact representation, or 2 for visualizing or writing down
the exact internal format. One particular case where such exact
representations are useful is in code generating tools.

Some other languages have support for floating point literals in other
bases. Notably, [C99/C++17 floating-point literals][C99] can be
written in hexadecimal, as e.g. `0xf.ffp8`, where the `p` indicates
that the exponent is a power of 2, and in the [Ada][Ada] programming
language, the corresponding syntax is `16#F.FF#E8`. The latter should
look familiar to Erlang users, because it is from Ada that the
`<Base>#<Numeral>` syntax was borrowed. (Ada however requires a final
`#` even for integers, e.g. `16#fffe#`.) Ada also allows base 2 in a
floating point number, e.g. `2#0.1111_1111#E8`, using underscores as
separators just like Erlang does.

Where Erlang differs from Ada is that Ada does not allow the base to
be larger than 16. Hence, in Ada, `2#111#`, `7#10#`, and `16#7#` are
all the same number, but `17#7#` is illegal, while Erlang allows any
base up to 36 in its integer literals, e.g. `36#z`. It should also be
noted that in the C99 hexadecimal literals, the letter `p` for the
exponent is a valid digit in bases above 25 in Erlang, whereas C99
only allows digits up to `f` (and could not use `e` for exponents in
hex). Because the Ada notation requires a `#` character before the
exponent, it has no ambiguity between digits and exponent indicator.

Staying with the Ada notation then seems to be the wise choice, both
for consistency and because it makes it trivial to keep allowing any
base up to 36 also for floating point literals in Erlang.

Examples:

2#0.111
2#0.10101#e8
16#ff.ff
16#fefe.fefe#e16
32#vrv.vrv#e15

It should be noted that both the base and the exponent are always
interpreted in base ten. Only the digits between the two `#`
characters are interpreted using the given base. Because Erlang uses
the `#` characters at the start of constructs such as maps `#{...}`,
we do not want to allow a final trailing `#` in a number, like Ada
does. If there is a second `#`, it must be followed by the exponent.

Specification
========================

In addition to the current based notation:

base # based_numeral

(borrowing Ada's terminology), where `base` is a decimal number and
`based_numeral` is a sequence of digits in `0-9` and `a-z` or `A-Z`,
optionally separated with `_`, we extend the parser to also allow:

base # based_numeral.based_numeral [ # exponent ]

where `exponent` is the letter `e` or `E` followed by an optionally
signed decimal number, exactly as in ordinary decimal floating point
literals.

Reference Implementation
------------------------

A [reference implementation][GitHub branch] exists in the
`hexbinfloat` branch of the author's GitHub account, together with a
[GitHub pull request][GitHub PR] to the Erlang/OTP repository.

[C99]: https://en.cppreference.com/w/cpp/language/floating_literal
"C99 and C++17 Floating-point Literal"

[Ada]: https://ada-lang.io/docs/arm/AA-2/AA-2.4#242--based-literals
"Ada Based Literals"

[GitHub branch]: https://github.com/richcarl/otp/tree/hexbinfloat
"Reference implementation branch on GitHub"

[GitHub PR]: https://github.com/erlang/otp/pull/9106
"GitHub Pull Request"

Copyright
=========

This document is placed in the public domain or under the CC0-1.0-Universal
license, whichever is more permissive.

[EmacsVar]: <> "Local Variables:"
[EmacsVar]: <> "mode: indented-text"
[EmacsVar]: <> "indent-tabs-mode: nil"
[EmacsVar]: <> "sentence-end-double-space: t"
[EmacsVar]: <> "fill-column: 70"
[EmacsVar]: <> "coding: utf-8"
[EmacsVar]: <> "End:"
[VimVar]: <> " vim: set fileencoding=utf-8 expandtab shiftwidth=4 softtabstop=4: "
Loading