Home > front end >  Round long double to unsigned long long in c
Round long double to unsigned long long in c

Time:08-27

Is there any built-in function in C to convert long double into unsigned long long?

As per this answer, it looks like double is not sufficient to represent some unsigned long long values. Correct me if long double is also not enough.

I also know that there's a function called, roundl that rounds a long double but returns a long double again.
Another function lround can only return long and works on a smaller range of values.

So given a long double, how to do I round it to the nearest integer of type, unsigned long long?
Thanks.

Related Question
Cast from unsigned long long to double and vice versa changes the value

CodePudding user response:

TL;DR use std::llroundl, assuming the initial value is smaller than 2^64. If it is bigger, then it wouldn't fit anyway, so up to you to decide what to do with it.

IEEE 754 floating point numbers can represent any integer up to a certain point. If you convert an integer to such a number, and then back to the same integral type, you'll get the exact same value back as long as the integer is not larger than the representable limit.

For double precision numbers, as explained in this answer, that's 2^53, which is big enough for all 32 bit integers. We can apply the same general formula for for quad precision numbers, and get 2^113, which is big enough for all 64 bit integers.

So, if long double on your implementation is a quad precision number, and unsigned long long is a 64 bit integer, then you can safely do the roundtrip:

unsigned long long i = /* a very big value */;
long double d = i; // safe because it's a widening conversion
assert(static_cast<unsigned long long>(d) == i); // should pass

Now, if you don't have an integer in that long double, then of course there'll be some loss, because that fraction will have to be cut. If you round the number first, you'll end up with an integer, and that is representable, so no loss (assuming it's not bigger than 2^113), but of course you'll still end up with a different number than the one you started with before the rounding.

long double d = /* a very big value */;
unsigned long long i = static_cast<unsigned long long>(std::roundl(d));

Or you can avoid the cast altogether by using std::llroundl:

long double d = /* a very big value */;
unsigned long long i = std::llroundl(d);

Although you'll need to be careful about negative numbers (but that's easy to check beforehand).

All of this assumes that your long double is never bigger than 2^64, but if it were, then you wouldn't be able to fit it into the unsigned long long anyway.

  •  Tags:  
  • c
  • Related