简体   繁体   中英

On the numeric range of a long double

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)

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM