Home > Enterprise >  On the numeric range of a long double
On the numeric range of a long double

Time:12-18

Compiling and running this code:

// List the range of the long double.
#include <stdio.h>
#include <float.h>
int main() {
  printf("Long double: %Lg - %Lg\n", LDBL_MIN, LDBL_MAX);
}

Gives this result:

Long double: 3.3621e-4932 - 1.18973e 4932

Yet this code:

#include <stdio.h>
#include <float.h>
int main() {
  long double ld = 1.18973e 4932;
  printf("Longest double: %Lg", ld);
}

Gives this warning when compiled:

gcc -std=gnu99 -o fj -Wall -Wno-format-overflow -g r2.c -lm

r2.c:4:3: warning: floating constant exceeds range of ‘double’ [-Woverflow] 4 | long double ld = 1.18973e 4932; | ^~~~

However, if you compile

#include <stdio.h>
#include <float.h>
int main() {
  long double ld = LDBL_MAX;
  printf("Longest double: %Lg\n", ld);
}

It compiles and runs:

Longest double: 1.18973e 4932

What's going on here? It should accept the numerical limit that was listed in the first program, but it does just fine with the LDBL_MAX version of it.

My compiler: gcc --version

gcc (Debian 10.2.1-6) 10.2.1 20210110

My computer:

AMD Ryzen 5 5600G with Radeon Graphics CPU MHz: 3057.560 BogoMIPS: 7785.19 CPU cache size: 512 KB Debian GNU/Linux 11 (bullseye)

CodePudding user response:

1.18973e 4932 is an out-of-range double constant.
LDBL_MAX is an in range long double constant.

Make the floating point constant a long double by appending an L.
Lower case l is an option too, yet harder to distinguish from 1.

// long double ld = 1.18973e 4932;
long double ld = 1.18973e 4932L;  // Yet this is not quite the max

// max value better with adequate precision as 
long double ld = 1.18973149535723176502e 4932L;

// Should print the same.
printf("Longest double: %.*Lg\n", LDBL_DECIMAL_DIG, ld);
printf("Longest double: %.*Lg\n", LDBL_DECIMAL_DIG, LDBL_MAX);

When coding near the limits, consider hex notation for better control in rounding issues.

long double ld = 1.1897315e 4932L;              --> Infinity
long double ld = 1.18973149535723177e 4932L;    --> Infinity
long double ld = 1.18973149535723176506e 4932L; --> Infinity
//               1.18973149535723176502e 4932L

long double ld = 0x1.fffffffffffffffep 16383L;
  • Related