I'd like to determine if a given 64-bit integer can be stored losslessly in a double. Right now I have this code:
static_cast<int64_t>(static_cast<double>(value)) == value
However, I believe this is not always accurate due to excess precision on some platforms.
Note that I'm not asking for the largest integer such that all smaller integers can be stored losslessly, which is 2^53. I need to know if a given integer N is losslessly storeable even if N+1 and N-1 are not.
Is there something in the standard library, maybe similar to std::numeric_limits
, that will tell me this?
Int64 (aka long): A signed integer with 64 bits (8 bytes) of space available. Single (aka float): A 32-bit floating point number. Double (aka double): A 64-bit floating-point number. Decimal (aka decimal): A 128-bit floating-point number with a higher precision and a smaller range than Single or Double.
If long long is present, it must have at least 64 bits, so casting from (u)int64_t to (unsigned) long long is value-preserving. If you need a type with exactly 64 bits, use (u)int64_t , if you need at least 64 bits, (unsigned) long long is perfectly fine, as would be (u)int_least64_t .
In a 64-bit compile, int64_t is long int , not a long long int (obviously).
A long on some systems is 32 bits (same as an integer), the int64_t is defined as a 64 bit integer on all systems (otherwise known as a long long). Portability may be affected using long, but using int64_t looks like it was created to increase portability.
As long as low bits are 0, you can have more high order bits set (because you can increase the double's exponent). I reduced the requirement to unsigned to make the bit shifting not have to worry about sign bits but I believe it should be adaptable.
bool fits_in_double_losslessly (uint64_t v)
{
const uint64_t largest_int = 1ULL << 53;
while ((v > largest_int) && !(v & 1))
{
v >>= 1;
}
return v <= largest_int;
}
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