1

Consider this simple code (t0.c):

#include <stdio.h>
#include <float.h>

#if DBL_HAS_SUBNORM == 1
double d = 0x23d804860c09bp-1119;

int main(void)
{
    printf("%a\n", d);
    return 0;
}
#endif

Invocation and output:

# host: CPU: Intel, OS: Windows 10
$ gcc t0.c -std=c11 && ./a.exe
0x1.2p-1070

# host: CPU: Intel, OS: Windows 10
$ clang t0.c -std=c11 && ./a.exe
0x1.2p-1070

# host: CPU: Intel, OS: Linux
$ gcc t0.c -std=c11 && ./a.out
0x0.0000000000012p-1022

# host: CPU: Intel, OS: Linux
$ clang t0.c -std=c11 && ./a.out
0x0.0000000000012p-1022

Question: For conversion specifier %a, how:

  • the exact format of hexadecimal floating-point constant is selected, and
  • the parameters of this hexadecimal floating-point constant are selected?

For example, why 0x1.2p-1070 and not 0x0.0000000000012p-1022 (or other variations) (and vise versa)?

pmor
  • 5,392
  • 4
  • 17
  • 36
  • 1
    The C standard leaves some choices about the `a` format up to the C implementation. It is specified in C 7.21.6.1 8. What is your specific question? Is it why Microsoft made their choice and GCC and Clang, or the Glibc library, made another choice? – Eric Postpischil Jun 02 '21 at 12:48
  • In what way is `0x23d804860c09bp-1119` a variation of `0x1.2p-1070`? – Eric Postpischil Jun 02 '21 at 12:48
  • Microsoft [documents](https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions?view=msvc-160) its usage: `a` Floating-point Signed hexadecimal double-precision floating-point value that has the form *[-]0xh.hhhhp±dd*, where *h.hhhh* are the hex digits (using lower case letters) of the mantissa, and *dd* are one or more digits for the exponent. The precision specifies the number of digits after the point. – Weather Vane Jun 02 '21 at 12:51
  • @EricPostpischil Yes, `0x23d804860c09bp-1119` is not a variation of `0x1.2p-1070`. Removed. Ok, the choice is up to the C implementation. – pmor Jun 02 '21 at 13:01

1 Answers1

2

C allows some latitude in the details

A double argument representing a floating-point number is converted in the style [-]0xh.hhhhp±d, where there is one hexadecimal digit (which is nonzero if the argument is a normalized floating-point number and is otherwise unspecified) before the decimal-point character and the number of hexadecimal digits after it is equal to the precision; if the precision is missing and FLT_RADIX is a power of 2, then the precision is sufficient for an exact representation of the value ... (more concerning base 10 encodings, Inf and NaN)
C2xdr § 7.21.6.1 8

Notable variations I have seen is if the first h digit is '0'-'F' or limited to '0'-'1'.


why 0x1.2p-1070 and not 0x0.0000000000012p-1022

Leading digit specified as non-zero for normal values. Yet as OP's value looks like a sub-normal one, either would have been acceptable. It is unspecified.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256