There is a base-2 scientific notation for floating point values: 0x3.ABCp-10
.
The significand is given in hexadecimal, and the exponent is given in decimal and interpreted
with respect to base 2. This notation is convenient for certain uses. For example, the smallest
normal IEEE-754 single precision value is readily written as 0x1.0p-126
. More
generally, this notation can be used when an exact object representation is desired (and the
floating point implementation uses a base-2 or base-2n representation).
The standard library outputs this representation via the hexfloat
manipulator
for ostreams, and via the a
/A
conversion specifiers in
printf
. Similarly,
formatted input works because strtod
recognises this representation (and
the semantics of formatted istream input operations and scanf
are defined in
terms of strtod
, but see below for a detail). We should also allow this
representation as a literal in the core language.
Note that the C language which is referenced by the C++ standard also allows this literal syntax.
This is a core language extension that adds a new numeric literal syntax. The proposed
syntax is ill-formed in the current working draft. Note that non-standard user-defined
literals must start with an underscore, and the standard library does not define a UDL
operator named p
or P
.
In section [lex.fcon] (2.13.4 in the working draft), change the grammar as follows (cf. C11 6.4.4.2/1).
.
digit-sequence
digit-sequence .
hexadecimal-fraction-constant:
hexadecimal-digit-sequenceopt .
hexadecimal-digit-sequence
hexadecimal-digit-sequence .
exponent-part:
e
signopt digit-sequence
E
signopt digit-sequence
binary-exponent-part:
p
signopt digit-sequence
P
signopt digit-sequence
sign: one of
+ -
digit-sequence:
digit
digit-sequence 'opt digit
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence 'opt hexadecimal-digit
hexadecimal-prefix: one of
0x 0X
floating-suffix: one of
f l F L
Change the subsequent paragraph 1 in the following way:
e
or E
,e
, E
, p
or P
,
an optionally
signed integer exponent, and an optional type suffix. The integer and
fraction parts both consist of either
a sequence of decimal (base ten) digits
1.602'176'565e-19
and 1.602176565e-19
have the same value.]
Either the integer part or the fraction part (not both) can be
omittede
E
)E
and the exponent (not both) can be omitted from a decimal floating literal.
The radix point (but not the exponent) can be omitted from a hexadecimal floating literal.
The integer part, the optional double
unless explicitly specified by a suffix. The suffixes f
and
F
specify float
, the suffixes l
and
L
specify long double
. If the scaled value is not
in the range of representable values for its type, the program is ill-formed.
Drafting note. We changed “significant” to “significand” and “decimal point” to “radix point”.
Also change the grammar in section [lex.ext] (2.13.8):
Although the library rules in [facet.num.get.members] say that formatted floating
point input uses the conversion rules of strtod
etc., the section also
restricts the set of characters permissible for floating point parsing to
"0123456789abcdefxABCDEFX+-"
, which is missing the values p
and P
. Should the present proposal succeed, we plan to either create a new
library proposal, or revisit LWG issue 2381
to add support for parsing hexadecimal floating point literals to the standard library.
Hexadecimal float literals are already supported as a vendor extension by several compilers: Clang, EDG, Embarcadero, GCC. Formatted input via iostreams is supported by libc++.