EDIT: After some discussion in the comments it came out that because of a luck of knowledge in how floating point numbers are implemented in C, I asked something different from what I meant to ask.
I wanted to use (do operations with) integers larger than those I can have with unsigned long long
(that for me is 8 bytes), possibly without recurring to arrays or bigint libraries. Since my long double
is 16 bytes, I thought it could've been possible by just switching type. It came out that even though it is possible to represent larger integers, you can't do operations -with these larger long double
integers- without losing precision. So it's not possible to achieve what I wanted to do. Actually, as stated in the comments, it is not possible for me. But in general, wether it is possible or not depends on the floating point characteristics of your long double
.
// end of EDIT
I am trying to understand what's the largest integer that I can store in a long double
.
I know it depends on environment which the program is built in, but I don't know exactly how. I have a sizeof(long double) == 16
for what is worth.
Now in this answer they say that the the maximum value for a 64-bit double should be 2^53, which is around 9 x 10^15, and exactly 9007199254740992
.
When I run the following program, it just works:
#include <stdio.h>
int main() {
long double d = 9007199254740992.0L, i;
printf("%Lf\n", d);
for(i = -3.0; i < 4.0; i++) {
printf("%.Lf) %.1Lf\n", i, d+i);
}
return 0;
}
It works even with 11119007199254740992.0L
that is the same number with four 1
s added at the start. But when I add one more 1
, the first printf
works as expected, while all the others show the same number of the first print.
So I tried to get the largest value of my long double
with this program
#include <stdio.h>
#include <math.h>
int main() {
long double d = 11119007199254740992.0L, i;
for(i = 0.0L; d+i == d+i-1.0; i++) {
if( !fmodl(i, 10000.0L) ) printf("%Lf\n", i);
}
printf("%.Lf\n", i);
return 0;
}
But it prints 0
.
(Edit: I just realized that I needed the condition !=
in the for
)
Always in the same answer, they say that the largest possible value of a double is DBL_MAX
or approximately 1.8 x 10^308.
I have no idea of what does it mean, but if I run
printf("%e\n", LDBL_MAX);
I get every time a different value that is always around 6.9 x 10^(-310).
(Edit: I should have used %Le
, getting as output a value around 1.19 x 10^4932)
I took LDBL_MAX
from here.
I also tried this one
printf("%d\n", LDBL_MAX_10_EXP);
That gives the value 4932
(which I also found in this C++ question).
Since we have 16 bytes for a long double
, even if all of them were for the integer part of the type, we would be able to store numbers till 2^128, that is around 3.4 x 10^38. So I don't get what 308, -310 and 4932 are supposed to mean.
Is someone able to tell me how can I find out what's the largest integer that I can store as long double
?
The number 2,147,483,647 (or hexadecimal 7FFFFFFF16) is the maximum positive value for a 32-bit signed binary integer in computing. It is therefore the maximum value for variables declared as integers (e.g., as int ) in many programming languages.
The int and double are major primitive data types. The main difference between int and double is that int is used to store 32 bit two's complement integer while double is used to store 64 bit double precision floating point value. In brief, double takes twice memory space than int to store data.
A 32-bit signed integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
Inasmuch as you express in comments that you want to use long double
as a substitute for long long
to obtain increased range, I assume that you also require unit precision. Thus, you are asking for the largest number representable by the available number of mantissa digits (LDBL_MANT_DIG
) in the radix of the floating-point representation (FLT_RADIX
). In the very likely event that FLT_RADIX == 2
, you can compute that value like so:
#include <float.h>
#include <math.h>
long double get_max_integer_equivalent() {
long double max_bit = ldexpl(1, LDBL_MANT_DIG - 1);
return max_bit + (max_bit - 1);
}
The ldexp
family of functions scale floating-point values by powers of 2, analogous to what the bit-shift operators (<<
and >>
) do for integers, so the above is similar to
// not reliable for the purpose!
unsigned long long max_bit = 1ULL << (DBL_MANT_DIG - 1);
return max_bit + (max_bit - 1);
Inasmuch as you suppose that your long double
provides more mantissa digits than your long long
has value bits, however, you must assume that bit shifting would overflow.
There are, of course, much larger values that your long double
can express, all of them integers. But they do not have unit precision, and thus the behavior of your long double
will diverge from the expected behavior of integers when its values are larger. For example, if long double
variable d
contains a larger value then at least one of d + 1 == d
and d - 1 == d
will likely evaluate to true.
You can print the maximum value on your machine using limits.h
, the value is ULLONG_MAX
In https://www.geeksforgeeks.org/climits-limits-h-cc/ is a C++ example.
The format specifier for printing unsigned long long with printf() is %llu
for printing long double it is %Lf
printf("unsigned long long int: %llu ",(unsigned long long) ULLONG_MAX);
printf("long double: %Lf ",(long double) LDBL_MAX);
https://www.tutorialspoint.com/format-specifiers-in-c
Is also in Printing unsigned long long int Value Type Returns Strange Results
Assuming you mean "stored without loss of information", LDBL_MANT_DIG
gives the number of bits used for the floating-point mantissa, so that's how many bits of an integer value that can be stored without loss of information.*
You'd need 128-bit integers to easily determine the maximum integer value that can be held in a 128-bit float, but this will at least emit the hex value (this assumes unsigned long long
is 64 bits - you can use CHAR_BIT
and sizeof( unsigned long long )
to get a portable answer):
#include <stdio.h>
#include <float.h>
#include <limits.h>
int main( int argc, char **argv )
{
int tooBig = 0;
unsigned long long shift = LDBL_MANT_DIG;
if ( shift >= 64 )
{
tooBig = 1;
shift -= 64;
}
unsigned long long max = ( 1ULL << shift ) - 1ULL;
printf( "Max integer value: 0x" );
// don't emit an extraneous zero if LDBL_MANT_DIG is
// exactly 64
if ( max )
{
printf( "%llx", max );
}
if ( tooBig )
{
printf( "%llx", ULLONG_MAX );
}
printf( "\n" );
return( 0 );
}
* - pedantically, it's the number of digits in FLT_RADIX
base, but that base is almost certainly 2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With